Trên cơ sở dữ liệu RAC sản xuất chính của tôi, tôi thấy có những khoảng thời gian chậm và sự kiện chờ đợi chiếm ưu thế, trên toàn hệ thống, là “con trỏ:pin S chờ trên X”. Sự kiện đến và đi, nhưng tôi thấy nó theo thời gian. Vì vậy, tôi cần phải hiểu rõ hơn về vấn đề này. Lưu ý rằng đây không phải là vấn đề RAC. Sự kiện này cũng có thể dễ dàng nhìn thấy trên các cơ sở dữ liệu đơn thể hiện. Khi tôi thấy điều này trên nhiều phiên bản của cơ sở dữ liệu Oracle RAC của mình, đó là do tôi có nhiều phiên từ cùng một ứng dụng được trải ra giữa các phiên bản, tất cả đều làm cùng một việc, do đó tất cả đều gặp phải vấn đề giống nhau.
Đầu tiên, sự kiện chờ đợi là gì? Bất kỳ sự chờ đợi nào của “con trỏ:” đều là tắc nghẽn trong Nhóm chia sẻ trong Vùng SQL. Cách đây khá lâu, phần này của Nhóm chia sẻ đã được bảo vệ bằng các chốt. Nhưng như trường hợp của nhiều khu vực trong Nhóm chia sẻ, Oracle hiện đang sử dụng mutexes. Với sự thay đổi trong cơ chế bảo vệ, giờ đây chúng tôi có các sự kiện chờ mới.
Trong trường hợp của sự kiện chờ cụ thể này, chúng tôi có một con trỏ đang muốn ghim Chia sẻ nhưng phải đợi một phiên khác để phát hành mutex eXclusive của nó. Một con trỏ đang cố gắng được phân tích cú pháp. Nhưng không thể phân tích cú pháp vì một phiên khác đang giữ cùng một mutex.
Có ba nguyên nhân chính khiến các phiên chờ đợi sự kiện này.
- Phân tích cú pháp khó cao
- Một số lượng lớn các phiên bản của câu lệnh SQL
- Lỗi
Thật không may, có một số lỗi liên quan đến sự kiện chờ đợi này. Hầu hết các phiên bản mà tôi đã thấy đều được sửa trong phiên bản 11.2.0.4 hoặc 12.1.0.1, vì vậy nếu bạn đang bị tụt hậu trong các phiên bản, hãy xem xét nâng cấp lên một trong các phiên bản Oracle mới hơn.
Vì vậy, hãy xem liệu chúng ta có thể xem qua một ví dụ để xác định nguyên nhân của vấn đề hay không. Để làm điều đó, tôi đã sử dụng truy vấn sau:
select s.inst_id as inst, s.sid as blocked_sid, s.username as blocked_user, sa.sql_id as blocked_sql_id, trunc(s.p2/4294967296) as blocking_sid, b.username as blocking_user, b.sql_id as blocking_sql_id from gv$session s join gv$sqlarea sa on sa.hash_value = s.p1 join gv$session b on trunc(s.p2/4294967296)=b.sid and s.inst_id=b.inst_id join gv$sqlarea sa2 on b.sql_id=sa2.sql_id where s.event='cursor: pin S wait on X';
Chạy điều này trong một trong các cơ sở dữ liệu RAC sản xuất của tôi, tôi nhận được kết quả sau:
INST BLOCKED_SID BLOCKED_USER BLOCKED_SQL_ID BLOCKING_SID BLOCKING_USER BLOCKING_SQL_ID ---- ----------- ------------ -------------- ------------ ------------- --------------- 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g
Điều đầu tiên cần lưu ý là mutex chỉ nằm trong phiên bản đó đối với cơ sở dữ liệu Oracle RAC. Đối với cơ sở dữ liệu đơn thể hiện, truy vấn ở trên sẽ vẫn hoạt động. Đối với Oracle RAC, kết quả từ truy vấn này sẽ hiển thị phiên bản nào đang gặp sự cố.
Trong ví dụ trên, chúng tôi có phiên 723 bị chặn bởi phiên 1226. Phiên 1226 bị chặn thêm bởi phiên 1796. Lưu ý rằng cả ba phiên đang phát hành cùng một truy vấn với SQL ID cn7m7t6y5h77g .
Bây giờ chúng ta đã biết ID SQL, chúng ta có thể dễ dàng truy vấn V $ SQL để xác định câu lệnh SQL liên quan đến vấn đề. Tôi đã sử dụng truy vấn này để có thêm thông tin.
select sql_id,loaded_versions,executions,loads,invalidations,parse_calls from gv$sql where inst_id=4 and sql_id='cn7m7t6y5h77g';
Kết quả từ truy vấn V $ SQL như sau:
SQL_ID LOADED_VERSIONS EXECUTIONS LOADS INVALIDATIONS PARSE_CALLS ------------- --------------- ---------- ---------- ------------- ----------- cn7m7t6y5h77g 1 105 546 308 3513
Bây giờ chúng ta có thể thấy rằng truy vấn này chỉ có 1 phiên bản trong Vùng SQL. Vì vậy, ngay lập tức, chúng tôi đã loại bỏ một trong những khu vực tiềm ẩn vấn đề. Trong một bài đăng trên blog trong tương lai, tôi sẽ thảo luận về các truy vấn có số lượng phiên bản cao trong Vùng SQL. Nhưng đó không phải là vấn đề của chúng tôi hôm nay nên chúng tôi tiếp tục.
Rõ ràng là ở trên có một số lượng rất cao các cuộc gọi phân tích cú pháp. Truy vấn chỉ được thực hiện 105 lần nhưng đã được phân tích cú pháp 3513 lần. Rất tiếc! Con số cao nếu tình trạng không hợp lệ cũng có thể liên quan đến vấn đề này.
Trong ví dụ này, bây giờ chúng ta có một ý tưởng tốt về vấn đề là gì. Đây là một vấn đề ứng dụng. Ứng dụng đang phân tích cú pháp quá mức truy vấn. Vì vậy, chúng tôi sẽ gửi nó trở lại quá trình phát triển và đào sâu vào mã ứng dụng. Các lý do thông thường cho việc phân tích cú pháp quá mức cần được xem xét.
Nếu số lượng phiên bản thấp và quá trình phân tích cú pháp / không hợp lệ / tải không phải là vấn đề, thì tôi sẽ nghi ngờ có lỗi và gửi SR đến Bộ phận hỗ trợ của Oracle.