Tôi đang làm việc với một cá nhân về một câu hỏi trong diễn đàn MOSC gần đây, nơi họ hỏi về cột TOP_LEVEL_RPI_CURSOR của chế độ xem V $ SQL_SHARED_CURSOR. Có rất ít tài liệu về những gì cột này đang cố gắng nói với DBA.
Tất cả các tài liệu Oracle nói rằng cột này chứa “(Y | N) Là con trỏ RPI cấp cao nhất”. Vậy điều đó có nghĩa là gì?
Tôi sẽ cho rằng người đọc bài đăng này đã quen thuộc với con trỏ chuột. Điều đó sẽ giúp tôi tiết kiệm một lượng lớn thông tin giới thiệu. Dạng xem V $ SQL_SHARED_CURSOR sẽ cho DBA biết lý do tại sao con trỏ con và con trỏ cha của nó có các phiên bản khác nhau trong Nhóm chia sẻ. Nếu cột OPTIMIZER_MISMATCH của con trỏ con chứa chữ ‘Y’ trong chế độ xem này, thì phiên thực thi con trỏ có cài đặt trình tối ưu hóa khác với phiên chịu trách nhiệm thực thi con trỏ mẹ.
Vậy điều đó có nghĩa là gì khi TOP_LEVEL_RPI_CURSOR được đặt thành Y cho một đứa trẻ? Tài liệu không rõ ràng. MOS có rất ít về chủ đề này. Và tất cả các lần truy cập Google của tôi vào cột này hầu như chỉ làm xuất hiện tài liệu. Để biết tại sao, cần biết rằng RPI là viết tắt của Recursive Program Interface. Đây là một phần của hạt nhân Oracle xử lý SQL đệ quy. Trong trường hợp của chúng tôi, nó đề cập đến thực tế là câu lệnh SQL được phát hành ở một “độ sâu” khác.
SQL đệ quy là gì? Đó là SQL được phát hành thay mặt bạn, có nghĩa là ở một độ sâu khác như tôi sẽ minh họa. Trước hết, Oracle luôn thực hiện SQL đệ quy. Ở mức cơ bản, khi bạn đưa ra “select * from table_name”, Oracle truy vấn Từ điển Dữ liệu để đảm bảo đối tượng tồn tại và bạn có quyền trên bảng đó. Oracle làm điều đó như thế nào? Nó sử dụng các câu lệnh SQL khác. Câu lệnh bạn đưa ra ở mức 0, mức cơ sở. Khi Oracle phát hành một câu lệnh SQL để kiểm tra xem bảng có tồn tại hay không, bảng đó sẽ ở cấp độ tiếp theo, cấp độ 1. Đôi khi, điều đó sẽ khiến các câu lệnh SQL khác được phát hành ở cấp độ tiếp theo, cấp độ 2.
Độ sâu của một câu lệnh SQL không chỉ giới hạn ở những gì Oracle đang làm trong nền, thay mặt bạn. Cân nhắc khi bạn thực hiện một thủ tục được lưu trữ. Lệnh gọi của bạn tới thủ tục được lưu trữ ở độ sâu 0. Bất kỳ câu lệnh SQL nào trong thủ tục được lưu trữ đều ở độ sâu 1. Nếu thủ tục được lưu trữ đó gọi một thủ tục khác, thì SQL trong thủ tục khác sẽ ở độ sâu 2.
Tôi đã sử dụng thông tin này về SQL đệ quy và độ sâu SQL để tạo một ví dụ đơn giản trong cơ sở dữ liệu Oracle 12.1.0.2 của mình. Đầu tiên, tôi đã tạo một thủ tục được lưu trữ.
create or replace procedure my_sysdate as v_dt date; begin select sysdate into v_dt from dual; end; /
Sau đó, tôi kích hoạt phiên SQL * Plus và bắt đầu theo dõi. Tôi đã phát hành cùng một câu lệnh SQL và sau đó tôi gọi thủ tục của mình.
SQL> alter session set sql_trace=true;
Session altered.
SQL> SELECT SYSDATE FROM DUAL 2 /
SYSDATE --------- 05-APR-16
SQL> exec my_sysdate;
PL/SQL procedure successfully completed.
SQL> exit
Khi tôi kiểm tra tệp theo dõi thô, tôi thấy hai lệnh gọi đến SYSDATE từ DUAL như sau:
THÔNG SỐ TRONG CURSOR # 140670990815296 len =24 dep =0 uid =9449 oct =3 lid =9449 tim =24905125014484 hv =124468195 ad =’81477be0 ′ sqlid =’ c749bc43qqfz3 ′ CHỌN TỔNG HỢP TỪ KÉP
THÔNG SỐ TRONG CURSOR # 140670907623848 len =24 dep =1 uid =9449 oct =3 lid =9449 tim =24905129780963 hv =124468195 ad =’81477be0 ′ sqlid =’ c749bc43qqfz3 ′ CHỌN TỔNG HỢP TỪ KÉP
Nếu bạn xem xét kỹ tệp theo dõi, bạn sẽ thấy tệp thứ hai ở độ sâu =1 là kết quả trực tiếp của quy trình được lưu trữ. Lưu ý rằng mặc dù thủ tục được lưu trữ của tôi được định nghĩa bằng tất cả các chữ thường, nhưng SQL được cấp ở độ sâu =1 vẫn là chữ hoa. Do đó, khi tôi phát hành cùng một câu lệnh SQL trực tiếp trong phiên SQL * Plus của mình (ở độ sâu =0), tôi phải sử dụng cùng một dạng chữ hoa của câu lệnh đó để nó có cùng giá trị SQL ID.
Tệp theo dõi cũng hiển thị ID SQL. Bây giờ tôi có thể truy vấn V $ SQL_SHARED_CURSOR cho giá trị SQL ID đó và cho biết rằng TOP_LEVEL_RPI_CURSOR được đặt cho con.
SQL> select sql_id,top_level_rpi_cursor from v$sql_shared_cursor where sql_id='c749bc43qqfz3';
SQL_ID T ------------- - c749bc43qqfz3 N c749bc43qqfz3 Y
Vì vậy, chúng tôi có bằng chứng của chúng tôi. Sự khác biệt duy nhất giữa hai con trỏ này là độ sâu mà chúng được thực thi. Tôi không chắc tại sao Oracle cần sự khác biệt này trong Nhóm chia sẻ. Nếu ai biết, hãy gửi cho tôi một dòng.
Thông thường, chúng tôi không quan tâm đến một vài phiên bản bổ sung, một vài con trỏ con cho một ID SQL nhất định. Nếu câu lệnh SQL của bạn có số lượng phiên bản cao, thì có thể không phải do các mức độ sâu khác nhau. Các lý do khác sẽ liên quan nhiều hơn đến lý do tại sao một câu lệnh SQL sẽ có nhiều con trỏ con, một số lượng lớn các phiên bản khác nhau. Nhưng điều này trả lời cho câu hỏi cột đó đang nói gì với chúng ta.