Oracle中的死锁

t2a7ltrp  于 2022-12-22  发布在  Oracle
关注(0)|答案(3)|浏览(123)

我想创建一个脚本,使进入死锁的oracle会话自动终止。是否有可能找到进入死锁的会话的会话ID。到目前为止,我不得不弹出数据库以消除死锁。是否有任何解决此问题的方法?

vbopmzt1

vbopmzt11#

我想创建一个脚本,在该脚本中,进入死锁的Oracle会话将被自动终止

编辑以更好的方式进行了解释,更正了几个句子,并添加了一个测试用例来演示死锁场景。

为什么要重新发明轮子?Oracle会自动检测死锁,引发ORA-00060: deadlock detected while waiting for resource,并回退死锁所涉及的事务处理之一(Oracle将其确定为牺牲品)。以前成功的事务处理不会回退。即使在死锁错误之后,如果发出提交,也会提交以前成功的事务处理。此时,另一个会话的事务也会成功,你可以提交一个提交。这里没有什么需要显式做的。死锁会被自动清除--你永远不需要清除它们。
通常,Oracle需要一两秒钟来检测死锁并抛出错误。
您可以尝试使用一个简单的测试用例,如下所示:Understanding Oracle Deadlock
我们来看一个测试案例-

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

注意每笔交易的时间,我已经把时间设定在计时上了,以便更好的理解。

届会:1次

12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;

1 row updated.

Elapsed: 00:00:00.00

届会: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;

此时,会话2保持等待

届会:1次

12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;

此时,SESSION 2是死锁的牺牲品,SESSION 1仍在等待。
我们来看一下SESSION 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>

因此,在会话2(即SID 14)中查看v$session详细信息时,状态为活动
让我们看看另一个会话的会话细节,为了方便起见,我们称之为会话3。请记住,会话1仍在等待。

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>

因此,对于其它会话,会话2,即SID 14,是非活动会话1仍然是等待,事件为enq: TX - row lock contention
让我们提交会话2-

12:22:18 SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
12:25:43 SQL>

此时,SESSION 1的锁被释放,让我们也提交会话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显示会话1在提交会话2之前等待了这么长时间。
总而言之,这是第一节课的全部内容-

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>

总结一下,这是第二节课的全部内容-

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>

现在,让我们看看哪个事务实际回滚,哪个事务提交-

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>

结论

在我看来,了解死锁的会话细节的最好方法是尽可能详细地记录细节。否则,DBA在没有记录正确信息的情况下进行调查将是一场噩梦。就此而言,如果没有详细记录死锁错误细节,即使是开发人员也会发现纠正和修复实际设计缺陷是一项艰巨的任务。最后,用一行语句总结一下:死锁是由设计缺陷引起的,Oracle只是受害者,而应用程序才是罪魁祸首。死锁是可怕的,但它们指出了迟早必须纠正的设计缺陷。

llew8vvj

llew8vvj2#

用户1

update table_c set id = 200 where id = 13;
BEGIN
DBMS_LOCK.sleep(14);
END;
/
update table_c set id = 200 where id = 15;

用户2

update table_c set id = 2000 where id = 15;

BEGIN
DBMS_LOCK.sleep(14);
END;
/

update table_c set id = 1000 where id = 13;
nue99wik

nue99wik3#

什么是死锁

当一个会话(A)需要另一个会话(B)占用的资源,但该会话也需要第一个会话(A)占用的资源时,就会发生死锁。可以涉及两个以上的会话,但概念是相同的。

ORA-60产生的诊断信息

ORA-60错误通常会将错误消息与创建的跟踪文件的名称一起写入预警.log中。其确切格式因Oracle发行版而异。跟踪文件将写入USER_DUMP_DEST或BACKGROUND_DUMP_DEST指示的目录中,具体取决于创建跟踪文件的进程类型。

解决死锁

Oracle是智能的,它能够在3秒内发现死锁情况。下面是避免数据库内部死锁的选项
要求死锁会话错误ORA-00060发出COMMIT或ROLLBACK
请求等待会话终止SQL /事务
在警报日志/跟踪文件中查找死锁所涉及的会话,并通知应用程序团队改进代码
作为一名DBA,无论何时您收到死锁警报,请立即联系应用程序团队并通知他们。

相关问题