【DB笔试面试664】在Oracle中,模拟死锁产生的一个场景。
作者:互联网
♣
题目 部分
在Oracle中,模拟死锁产生的一个场景。
♣
答案部分
Oracle中的死锁比较复杂,产生死锁的原因也有很多种,曾经有面试官让面试人员口头模拟死锁产生的一个场景。
下面给出一个基于事务相互更新导致死锁的模拟实验:
1、创建两个简单的表A和B,每个表中仅仅包含一个字段ID,这里的实验环境为集群。
1SYS@RACLHR2> CREATE TABLE A (ID INT); 2Table created. 3SYS@RACLHR2> CREATE TABLE B (ID INT); 4Table created.
2、每张表中仅插入一条数据,A表插入1,B表插入2。
1SYS@RACLHR2> INSERT INTO A VALUES (1); 21 row created. 3SYS@RACLHR2> INSERT INTO B VALUES (2); 41 row created. 5SYS@RACLHR2> COMMIT; 6Commit complete. 7SYS@RACLHR2> SELECT * FROM A; 8 ID 9---------- 10 1 11SYS@RACLHR2> SELECT * FROM B; 12 ID 13---------- 14 2
3、在第一个会话SESSION1中更新表A中的记录“1”为“10000”,且不提交;在第二个会话SESSION2中更新表B中的记录“2”为“20000”,且不提交。
SESSION1的情况如下所示:
1SYS@RACLHR2> SELECT A.SID, 2 2 B.SERIAL# , 3 3 C.SPID 4 4 FROM V$MYSTAT A, 5 5 V$SESSION B , 6 6 V$PROCESS C 7 7 WHERE A.SID = B.SID 8 8 AND B.PADDR=C.ADDR 9 9 AND ROWNUM = 1; 10 SID SERIAL# SPID 11---------- ---------- ------------------------ 12 133 3 20906088 13SYS@RACLHR2> UPDATE A SET ID = 10000 WHERE ID = 1; 141 row updated.
SESSION2的情况如下所示:
1SYS@RACLHR2> SELECT A.SID, 2 2 B.SERIAL# , 3 3 C.SPID 4 4 FROM V$MYSTAT A, 5 5 V$SESSION B , 6 6 V$PROCESS C 7 7 WHERE A.SID = B.SID 8 8 AND B.PADDR=C.ADDR 9 9 AND ROWNUM = 1; 10 SID SERIAL# SPID 11---------- ---------- ------------------------ 12 195 21 11010172 13SYS@RACLHR2> UPDATE B SET ID = 20000 WHERE ID = 2; 141 row updated.
此时,执行过程没有任何问题。现在接着执行下面的操作,首先回到会话SESSION1中,更新表B的记录,此时出现了会话阻塞,更新不能继续:
1SYS@RACLHR2> UPDATE B SET ID = 10000 WHERE ID = 2;
这里出现了锁等待(阻塞)的现象,因为在SESSION2中已经对这条数据执行过UPDATE操作,没有提交表示已经对该行加了行级锁,如下所示:
1SYS@RACLHR2> SET LINE 9999 2SYS@RACLHR2> SELECT A.INST_ID, 3 2 A.SID, 4 3 A.SERIAL#, 5 4 A.SQL_ID, 6 5 A.BLOCKING_INSTANCE, 7 6 A.BLOCKING_SESSION, 8 7 A.EVENT 9 8 FROM GV$SESSION A 10 9 WHERE A.USERNAME IS NOT NULL 11 10 AND A.STATUS = 'ACTIVE' 12 11 AND A.BLOCKING_SESSION IS NOT NULL ; 13 INST_ID SID SERIAL# SQL_ID BLOCKING_INSTANCE BLOCKING_SESSION EVENT 14---------- ---------- ---------- ------------- ----------------- ---------------- ------------------------------ 15 2 133 3 6k793mj0duubw 2 195 enq: TX - row lock contention
可以通过V$SESSION视图看到,实例2的195阻塞了实例2的133会话,即本实验中的SESSION2阻塞了SESSION1。
4、接下来再执行一条SQL后,死锁就会产生了。在SESSION2中,更新表A的记录。
1SYS@RACLHR2> UPDATE A SET ID = 10000 WHERE ID = 1;
由于SESSION1没有提交,所以,SESSION2这里还是长时间地等待即会话HANG住,但是SESSION2这里已经发生了死锁,此时去第一个会话SESSION1可以看到原先一直在等待的SQL语句报了如下的错误:
1SYS@RACLHR2> UPDATE B SET ID = 10000 WHERE ID = 2; 2UPDATE B set id = 10000 WHERE id = 2 3 * 4ERROR at line 1: 5ORA-00060: deadlock detected while waiting for resource
若此时查询V$SESSION视图,则可以看到实例2的133阻塞了实例2的195会话,即本实验中的SESSION1阻塞了SESSION2,和刚才的阻塞情况相反,说明Oracle做了自动处理:
1SYS@RACLHR2> SET LINE 9999 2SYS@RACLHR2> SELECT A.INST_ID, 3 2 A.SID, 4 3 A.SERIAL#, 5 4 A.SQL_ID, 6 5 A.BLOCKING_INSTANCE, 7 6 A.BLOCKING_SESSION, 8 7 A.EVENT 9 8 FROM GV$SESSION A 10 9 WHERE A.USERNAME IS NOT NULL 11 10 AND A.STATUS = 'ACTIVE' 12 11 AND A.BLOCKING_SESSION IS NOT NULL ; 13 INST_ID SID SERIAL# SQL_ID BLOCKING_INSTANCE BLOCKING_SESSION EVENT 14---------- ---------- ---------- ------------- ----------------- ---------------- ------------------------------ 15 2 195 21 5q7t3877fdu3n 2 133 enq: TX - row lock contention
标签:664,DB,死锁,SESSION,SID,----------,RACLHR2,WHERE,ID 来源: https://blog.51cto.com/lhrbest/2707308