saup007 发表于 2013-11-18 17:26:26

奇怪的deadlock -- 死锁

本帖最后由 saup007 于 2013-11-18 17:27 编辑

现在业务遇到二种情况的死锁,很奇怪。这个问题困惑很久了。

这二张表,没有主外键关系。

1、update和insert产生死锁

我知道insert,主键重复覆盖会产生死锁,但update和insert怎么产生的死锁呢?

SQL1:
update table1 set ... where ...

SQL2:
insert into table2 values(......)

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-003f0006-000619e2       566    1739     X            478    1749           X
TX-00160000-00117cf1       478    1749     X            566    1739           S

session 1739: DID 0001-0236-0000CB67    session 1749: DID 0001-01DE-00014EA2
session 1749: DID 0001-01DE-00014EA2    session 1739: DID 0001-0236-0000CB67


--insert与insert产生死锁,但update和insert怎么会产生死锁,不知道。
CREATE TABLE T1 (col1 NUMBER NOT NULL, col2 NUMBER);
ALTER TABLE T1 ADD CONSTRAINT T1_UNIQUE UNIQUE (col1, col2);

session1> INSERT INTO T1 VALUES (1, NULL);
session2> INSERT INTO T1 VALUES (2, NULL);
session2> INSERT INTO T1 VALUES (1, NULL); -- <= this will wait on session1
session1> INSERT INTO T1 VALUES (2, NULL); -- <= Deadlock !



2、两张没有主外键的表,也有死锁

通过deadlock graph,只能找到导致deadlock的一条数据,但怎么产生的没有头绪。。

SQL1:
select * from table1 where ... for update;

SQL2:
update table2 set ... where ... RETURNING...

deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-002a0013-000b7c02       564    1246     X            268    1160           X
TX-002c001b-000a3411       268    1160     X            564    1246           X

session 1246: DID 0001-0234-00001EC4    session 1160: DID 0001-010C-00128EE3
session 1160: DID 0001-010C-00128EE3    session 1246: DID 0001-0234-00001EC4

Rows waited on:
  Session 1246: obj - rowid = 00038F03 - AAA48DAAeAABECqAAw
  (dictionary objn - 233219, file - 30, block - 278698, slot - 48)
  Session 1160: obj - rowid = 00039287 - AAA5KHAAgAAAJcQAC4
  (dictionary objn - 234119, file - 32, block - 38672, slot - 184)

Maclean Liu(刘相兵 发表于 2013-11-18 18:40:39

ORA-60 有trace 的,给出完整trace

saup007 发表于 2013-11-19 10:17:18

Maclean Liu(刘相兵 发表于 2013-11-18 18:40 static/image/common/back.gif
ORA-60 有trace 的,给出完整trace

给出完整的trace文件了。

ora_31908.trc  这个trace,二种情况的deadlock都在里面,Current SQL 在trace文件后面有insert和update的死锁(110869行)。
ora_31899.trc  这个trace,只有select ... for update  和 update 语句的deadlock。

谢谢。

主要是二张看似没有什么关系的表,也没有主外键关系。

Maclean Liu(刘相兵 发表于 2013-11-19 15:20:43

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-002a000c-000b7ac7       124    1223     X            367    2078           X
TX-0032001d-0006d9a1       367    2078     X            124    1223           X

session 1223: DID 0001-007C-00223740        session 2078: DID 0001-016F-00013484
session 2078: DID 0001-016F-00013484        session 1223: DID 0001-007C-00223740

Rows waited on:
  Session 1223: obj - rowid = 00039287 - AAA5KHAAgAAAJcQACo
  (dictionary objn - 234119, file - 32, block - 38672, slot - 168)
  Session 2078: obj - rowid = 00038F03 - AAA48DAAeAABDTzAAm
  (dictionary objn - 233219, file - 30, block - 275699, slot - 38)



LOG_RECORD_DETAIL         objn - 233219
LOG_RECORD_IDCARD         objn - 234119,


session 2078 先锁住了 LOG_RECORD_IDCARD ,之后尝试锁LOG_RECORD_DETAIL
session 1223 先锁住了 LOG_RECORD_DETAIL ,之后尝试锁 LOG_RECORD_IDCARD

session 2078的SQL执行顺序:

1、  SELECT D.FIRST_LOGIN_TIME, D.ONLINE_SECOND_TOTAL, D.OFFLINE_SECOND_TOTAL, D.USER_COUNT FROM LOG_RECORD_IDCARD D WHERE GAME_ID = :B2 AND ID_CODE = :B1 FOR UPDATE
  2、 UPDATE LOG_RECORD_DETAIL SET LOGOUT_TIME = :B1 , ROLE_LEVEL = :B6 , MONEY1 = :B5 , MONEY2 = :B4 , EXPERIENCE = :B3 WHERE LOGIN_ID = :B2 RETURNING SERVER_ID, (:B1 - LOGIN_TIME) * 86400, LOGIN_IP, PROVINCE_CODE, CITY_CODE INTO :O0 ,:O1 ,:O2 ,:O3 ,:O4


session 1223:

1、UPDATE LOG_RECORD_DETAIL SET LOGOUT_TIME = :B1 , ROLE_LEVEL = :B6 , MONEY1 = :B5 , MONEY2 = :B4 , EXPERIENCE = :B3 WHERE LOGIN_ID = :B2 RETURNING SERVER_ID, (:B1 - LOGIN_TIME) * 86400, LOGIN_IP, PROVINCE_CODE, CITY_CODE INTO :O0 ,:O1 ,:O2 ,:O3 ,:O4


2、SELECT D.FIRST_LOGIN_TIME, D.ONLINE_SECOND_TOTAL, D.OFFLINE_SECOND_TOTAL, D.USER_COUNT FROM LOG_RECORD_IDCARD D WHERE GAME_ID = :B2 AND ID_CODE = :B1 FOR UPDATE

saup007 发表于 2013-11-19 16:02:08

Maclean Liu(刘相兵 发表于 2013-11-19 15:20 static/image/common/back.gif
Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Reso ...15:49:15 saup@TEST11G> select * from t1;

      COL1         COL2
---------- ----------
         1
         2

15:49:19 saup@TEST11G>
15:49:23 saup@TEST11G> select * from t2;

       ID1          ID2
---------- ----------
         1            1
         1            2
         2            1
         2            2
session 1:
15:49:40 saup@TEST11G> select * from t1 where col1=1 for update;

      COL1         COL2
---------- ----------
         1

session 2
15:49:57 saup@TEST11G> update t2 set id2=100 where id1=1;

2 rows updated.

session 1
15:52:33 saup@TEST11G> update t2 set id2=100 where id1=1;
update t2 set id2=100 where id1=1

(在session 2执行完后,deadlock)

session 2:

15:50:17 saup@TEST11G>  select * from t1 where col1=1 for update;

      COL1         COL2
---------- ----------
         1

除了主外键,二张表deadlock还可以这样。

Maclean Liu(刘相兵 发表于 2013-11-19 16:14:50

saup007 发表于 2013-11-19 16:02 static/image/common/back.gif
除了主外键,二张表deadlock还可以这样。

你给的例子比 主外键的例子更常见吧?

ocp课程介绍的死锁 就是这种最简单的啊

saup007 发表于 2013-11-19 16:16:59

本帖最后由 saup007 于 2013-11-19 16:20 编辑

t1 表中 col1、col2 是主键,具有唯一性

--session 1

insert into t1 values(3,null);

--session 2

update t2 set id2=200 where id1=1

--session 2 -- 被阻塞住,在下面session 2执行完后,此处死锁

insert into t1 values(3,null);

--session 1 -- 被session 2阻塞

update t2 set id2=200 where id1=1;



saup007 发表于 2013-11-19 16:21:48

Maclean Liu(刘相兵 发表于 2013-11-19 16:14 static/image/common/back.gif
你给的例子比 主外键的例子更常见吧?

ocp课程介绍的死锁 就是这种最简单的啊 ...

我脑盘筋没转过来弯。。。没想通。。不知怎么的,就是绕不过来。现在明白了。
页: [1]
查看完整版本: 奇怪的deadlock -- 死锁