Tôi muốn tạo một tập lệnh trong đó các phiên oracle gặp bế tắc sẽ tự động bị giết
CHỈNH SỬA Được giải thích theo cách tốt hơn, sửa một số câu và thêm một trường hợp thử nghiệm để chứng minh tình huống bế tắc.
Tại sao bạn muốn phát minh lại bánh xe? Oracle tự động phát hiện bế tắc, ném ORA-00060: deadlock detected while waiting for resource
, và khôi phục một trong các giao dịch liên quan đến bế tắc mà Oracle đã quyết định là nạn nhân. Các giao dịch thành công trước đó không được quay trở lại. Ngay cả sau khi lỗi deadlock, nếu một cam kết được đưa ra, thì giao dịch thành công trước đó sẽ được cam kết. Tại thời điểm này, giao dịch của phiên khác cũng sẽ thành công và bạn có thể đưa ra cam kết. Không có gì mà bạn cần phải làm ở đây một cách rõ ràng. Các bế tắc tự động được xóa - bạn không bao giờ cần phải xóa họ.
Thông thường, Oracle mất một hoặc hai giây để phát hiện bế tắc và xử lý lỗi.
Bạn có thể thử với một trường hợp thử nghiệm đơn giản như được trình bày ở đây:Hiểu về Oracle Deadlock
Hãy xem xét một trường hợp thử nghiệm -
SQL> CREATE TABLE t_test(col_1 NUMBER, col_2 NUMBER);
Table created
SQL> INSERT INTO t_test VALUES(1,2);
1 row inserted
SQL> INSERT INTO t_test VALUES(3,4);
1 row inserted
SQL> COMMIT;
Commit complete
SQL> SELECT * FROM t_test;
COL_1 COL_2
---------- ----------
1 2
3 4
Lưu ý thời gian của mỗi giao dịch, tôi đã đặt thời gian về thời gian để hiểu rõ hơn.
PHẦN:1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
PHẦN:2
12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;
1 row updated.
Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
Tại thời điểm này, PHẦN 2 tiếp tục chờ .
PHẦN:1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
Tại thời điểm này, PHẦN 2 là nạn nhân của bế tắc, PHẦN 1 vẫn đang chờ đợi.
Hãy xem chi tiết phiên từ PHẦN 2 -
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
14 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Application VALID enq: TX - row lock contention
Elapsed: 00:00:00.00
12:22:18 SQL>
Vì vậy, v$session
chi tiết khi được xem trong PHẦN 2 , tức là SID 14, cho biết trạng thái là HOẠT ĐỘNG .
Hãy xem chi tiết phiên từ một phiên khác, hãy gọi nó là PHIÊN 3 Vì lợi ích. Hãy nhớ rằng, PHẦN 1 vẫn đang đợi.
SQL> set time on timing on
12:24:41 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe'
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- ---------- ----------- ------------------------------
13 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
14 INACTIVE sqlplus.exe WAITING Idle NO HOLDER SQL*Net message from client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Applicatio VALID enq: TX - row lock contention
n
Elapsed: 00:00:00.01
12:24:44 SQL>
Vì vậy, đối với các phiên khác, PHIÊN 2 , tức là SID 14, là KHÔNG TÁC ĐỘNG . PHẦN 1 vẫn đang CHỜ ĐỢI với sự kiện enq: TX - row lock contention
.
Hãy cam kết PHẦN 2 -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
Tại thời điểm này, khóa được phát hành cho PHẦN 1 , hãy cùng cam kết phiên 1 -
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
1 row updated.
Elapsed: 00:08:27.29
12:25:43 SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
12:26:26 SQL>
Elapsed: 00:08:27.29
hiển thị PHẦN 1 đã đợi lâu như vậy cho đến PHIÊN BẢN 2 đã được cam kết.
Tóm lại, đây là toàn bộ câu chuyện của phần 1 -
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
1 row updated.
Elapsed: 00:08:27.29
12:25:43 SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
12:26:26 SQL>
Tóm lại, đây là toàn bộ câu chuyện của phần 2 -
12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;
1 row updated.
Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
UPDATE t_test SET col_1 = 7 WHERE col_2=2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:24.47
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
14 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Application VALID enq: TX - row lock contention
Elapsed: 00:00:00.00
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
Bây giờ, hãy xem giao dịch nào thực sự được khôi phục và giao dịch nào đã được cam kết -
12:25:43 SQL> select * from t_test;
COL_1 COL_2
---------- ----------
5 2
8 4
Elapsed: 00:00:00.00
12:30:36 SQL>
Kết luận
Theo tôi, cách tốt nhất để biết chi tiết về phiên bế tắc là ghi lại chi tiết càng dài càng tốt. Mặt khác, thật là một cơn ác mộng đối với một DBA khi điều tra mà không có thông tin thích hợp được ghi lại. Đối với vấn đề đó, ngay cả một Nhà phát triển cũng sẽ thấy đó là một nhiệm vụ cực kỳ nghiêm trọng để khắc phục và sửa lỗi thiết kế thực tế nếu chi tiết lỗi bế tắc không được ghi lại một cách chi tiết. Và để kết thúc với một tuyên bố lót, Một bế tắc là do lỗi thiết kế, Oracle chỉ là nạn nhân và ứng dụng là thủ phạm. Bế tắc thật đáng sợ, nhưng chúng chỉ ra những sai sót trong thiết kế sớm hay muộn cũng phải được khắc phục.