Oracle 死锁及解决办法

一、构建死锁

1.1、使用sys用户登陆并更新scott.emp表,但是不要提交

[[email protected] ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Thu Apr 11 15:46:03 2019

Copyright (c) 1982, 2013, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> set linesize 120
SQL> select * from scott.emp;

     EMPNO ENAME      JOB	       MGR HIREDATE		     SAL       COMM	DEPTNO
---------- ---------- --------- ---------- ------------------ ---------- ---------- ----------
      7369 SMITH      CLERK	      7902 17-DEC-80		     800		    20
      7499 ALLEN      SALESMAN	      7698 20-FEB-81		    1600	300	    30
      7521 WARD       SALESMAN	      7698 22-FEB-81		    1250	500	    30
      7566 JONES      MANAGER	      7839 02-APR-81		    2975		    20
      7654 MARTIN     SALESMAN	      7698 28-SEP-81		    1250       1400	    30
      7698 BLAKE      MANAGER	      7839 01-MAY-81		    2850		    30
      7782 CLARK      MANAGER	      7839 09-JUN-81		    2450		    10
      7788 SCOTT      ANALYST	      7566 19-APR-87		    3000		    20
      7839 KING       PRESIDENT 	   17-NOV-81		    5000		    10
      7844 TURNER     SALESMAN	      7698 08-SEP-81		    1500	  0	    30
      7876 ADAMS      CLERK	      7788 23-MAY-87		    1100		    20

     EMPNO ENAME      JOB	       MGR HIREDATE		     SAL       COMM	DEPTNO
---------- ---------- --------- ---------- ------------------ ---------- ---------- ----------
      7900 JAMES      CLERK	      7698 03-DEC-81		     950		    30
      7902 FORD       ANALYST	      7566 03-DEC-81		    3000		    20
      7934 MILLER     CLERK	      7782 23-JAN-82		    1300		    10

14 rows selected.

SQL> 
SQL> update scott.emp set sal=0;

14 rows updated.

SQL>

1.2、使用scott用户执行delete操作

[[email protected] ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Thu Apr 11 15:44:19 2019

Copyright (c) 1982, 2013, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> alter user scott account unlock identified by oracle;

User altered.

SQL> conn scott/oracle;
Connected.
SQL> 
SQL> 
SQL> set linesize 120
SQL> select * from emp; 

     EMPNO ENAME      JOB	       MGR HIREDATE		     SAL       COMM	DEPTNO
---------- ---------- --------- ---------- ------------------ ---------- ---------- ----------
      7369 SMITH      CLERK	      7902 17-DEC-80		     800		    20
      7499 ALLEN      SALESMAN	      7698 20-FEB-81		    1600	300	    30
      7521 WARD       SALESMAN	      7698 22-FEB-81		    1250	500	    30
      7566 JONES      MANAGER	      7839 02-APR-81		    2975		    20
      7654 MARTIN     SALESMAN	      7698 28-SEP-81		    1250       1400	    30
      7698 BLAKE      MANAGER	      7839 01-MAY-81		    2850		    30
      7782 CLARK      MANAGER	      7839 09-JUN-81		    2450		    10
      7788 SCOTT      ANALYST	      7566 19-APR-87		    3000		    20
      7839 KING       PRESIDENT 	   17-NOV-81		    5000		    10
      7844 TURNER     SALESMAN	      7698 08-SEP-81		    1500	  0	    30
      7876 ADAMS      CLERK	      7788 23-MAY-87		    1100		    20

     EMPNO ENAME      JOB	       MGR HIREDATE		     SAL       COMM	DEPTNO
---------- ---------- --------- ---------- ------------------ ---------- ---------- ----------
      7900 JAMES      CLERK	      7698 03-DEC-81		     950		    30
      7902 FORD       ANALYST	      7566 03-DEC-81		    3000		    20
      7934 MILLER     CLERK	      7782 23-JAN-82		    1300		    10

14 rows selected.

SQL> 
SQL> delete from emp where sal='5000';

至此,死锁产生了!

二、通过等待时间来找出死锁的原因

2.1、通过查看等待事件来找出问题原因:select * from v$system_wait_class order by time_waited desc;

SQL> select * from v$system_wait_class order by time_waited desc;

WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS							   TOTAL_WAITS TIME_WAITED TOTAL_WAITS_FG TIME_WAITED_FG
------------- ----------- ---------------------------------------------------------------- ----------- ----------- -------------- --------------
   2723168908		6 Idle									596534	  23315995	     3042	 1930587
   4217450380		1 Application								  1106	     59652	     1035	   59628
   1740759767		8 User I/O								 17015	     36980	     5396	   23605
   1893977003		0 Other 								301901	     10255	     2938	    3089
   4108307767		9 System I/O								 19135	      9716	      244	     420
   3875070507		4 Concurrency								 31145	      1357	     2502	     553
   3871361733	       11 Cluster								  2983	      1326	     1331	     509
   4166625743		3 Administrative							     3		70		2	      20
   3386400367		5 Commit								     9		15		8	      14
   3290255840		2 Configuration 							    22		 2		6	       1
   2000153315		7 Network								  1926		 0	     1876	       0

11 rows selected.

SQL>/  

WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS							   TOTAL_WAITS TIME_WAITED TOTAL_WAITS_FG TIME_WAITED_FG
------------- ----------- ---------------------------------------------------------------- ----------- ----------- -------------- --------------
   2723168908		6 Idle									599583	  23488205	     3050	 1936358
   4217450380		1 Application								  1112	     62408	     1041	   62384
   1740759767		8 User I/O								 17072	     37002	     5396	   23605
   1893977003		0 Other 								302696	     10299	     2941	    3107
   4108307767		9 System I/O								 19247	      9739	      244	     420
   3875070507		4 Concurrency								 31186	      1357	     2502	     553
   3871361733	       11 Cluster								  2983	      1326	     1331	     509
   4166625743		3 Administrative							     3		70		2	      20
   3386400367		5 Commit								     9		15		8	      14
   3290255840		2 Configuration 							    22		 2		6	       1
   2000153315		7 Network								  1934		 0	     1884	       0

11 rows selected.

SQL> /

WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS							   TOTAL_WAITS TIME_WAITED TOTAL_WAITS_FG TIME_WAITED_FG
------------- ----------- ---------------------------------------------------------------- ----------- ----------- -------------- --------------
   2723168908		6 Idle									605844	  23751088	     3066	 1954101
   4217450380		1 Application								  1124	     68170	     1053	   68146
   1740759767		8 User I/O								 17177	     37056	     5396	   23605
   1893977003		0 Other 								304295	     10306	     2941	    3107
   4108307767		9 System I/O								 19432	      9784	      244	     420
   3875070507		4 Concurrency								 31258	      1359	     2502	     553
   3871361733	       11 Cluster								  2995	      1326	     1331	     509
   4166625743		3 Administrative							     3		70		2	      20
   3386400367		5 Commit								     9		15		8	      14
   3290255840		2 Configuration 							    22		 2		6	       1
   2000153315		7 Network								  1950		 0	     1900	       0

11 rows selected.

SQL> 

Oracle 死锁及解决办法

2.2、确定了是应用程序这个大类后,然后再来根据WAIT_CLASS#找出具体小类

SQL> select event from v$SYSTEM_EVENT where wait_class#=1;

EVENT
----------------------------------------------------------------
enq: TM - contention
enq: TX - row lock contention
enq: RC - Result Cache: Contention
SQL*Net break/reset to client
enq: UL - contention

SQL> 

2.3、进一步确认等待是由哪个小类造成的:

select EVENT,TOTAL_WAITS,TIME_WAITED from V$SYSTEM_EVENT where wait_class#=1;
SQL> select EVENT,TOTAL_WAITS,TIME_WAITED from V$SYSTEM_EVENT where wait_class#=1;

EVENT								 TOTAL_WAITS TIME_WAITED
---------------------------------------------------------------- ----------- -----------
enq: TM - contention							  87	       7
enq: TX - row lock contention						   1	  101602
enq: RC - Result Cache: Contention					   1	      19
SQL*Net break/reset to client						1108	      18
enq: UL - contention							   1	       0

SQL>

2.4、再通过事件去搜寻是哪个会话

select sid,event from v$session where event like '%enq%row%';
SQL> select sid,event from v$session where event like '%enq%row%';

       SID EVENT
---------- ----------------------------------------------------------------
       133 enq: TX - row lock contention

SQL> 

2.5、再看看133号会话是谁

select sid,username,sql_id from v$session where sid=133;
SQL> select sid,username,sql_id from v$session where sid=133;

       SID USERNAME			  SQL_ID
---------- ------------------------------ -------------
       133 SCOTT			  d6u0atr2tnby0

SQL>

2.6、通过SQL_ID找到SQL语句

select sql_text from v$sql where sql_id='d6u0atr2tnby0';
SQL> select sql_text from v$sql where sql_id='d6u0atr2tnby0';

SQL_TEXT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
delete from emp where sal='5000'

SQL>

2.7、确定是谁和他发生了冲突

select SID,SERIAL#,USERNAME,status from V$SESSION where SID in (select BLOCKING_SESSION from v$SESSION);
SQL> select SID,SERIAL#,USERNAME from V$SESSION where SID in (select BLOCKING_SESSION from v$SESSION);

       SID    SERIAL# USERNAME
---------- ---------- ------------------------------
	12	   33 SYS

SQL>

2.8、杀掉和他冲突的用户

alter system kill session '12,33' immediate;
SQL> alter system kill session '12,33' immediate;

System altered.

SQL>

2.9、再看看被阻塞的scott用户,已经delete成功了

SQL> delete from emp where sal='5000';

1 row deleted.

SQL>

2.10、如果要快速释放资源,执行如下语句

select PADDR from v$session where SID=12 and SERIAL#=33;
select SPID,USERNAME from v$process where ADDR='XXXX';
 kill -9 SPID

至此,死锁问题已解决!

三、如果嫌上面太啰嗦,也可以这样来做

执行如下SQL

select SID,SERIAL#,USERNAME,status from V$SESSION where SID in (select BLOCKING_SESSION from v$SESSION);

或者:

  select s.username,l.object_id, l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program from v$session s,v$locked_object l where s.sid = l.session_id;

然后直接

alter system kill session 'SID,SERIAL#' immediate;

这样就可以了!