Oracle/Oh Oracle

Deaclock(교착상태)

darkturtle26 2018. 3. 7. 11:23

Deaclock(교착상태)


: Deadlock 발생 시, Oracle 에 의해 자동으로 Deadlock 상태를 해소 되나, TX-LOCK 이 유발됨 

TX-LOCK 해소를 위해서, Application 에서 Deadlock Error 발생 시, Rollback 처리가 필요함 




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
SYS@TGDB=> create user test identified by test default tablespace users 
  2  temporary tablespace temp quota unlimited on users ;
 
User created.
 
SYS@TGDB=> grant connect, create table to test ;
 
Grant succeeded.
 
SYS@TGDB=> grant execute on dbms_lock to test ;
 
Grant succeeded.
 
SYS@TGDB=> grant select on v_$mystat to test ;
 
Grant succeeded.
 
 
 
SYS@TGDB=> 
 
-- 테스트 세션 1(52)
SYS@TGDB=> conn test/test
Connected.
 
TEST@TGDB=> col ses_info new_value sname
TEST@TGDB=> set termout off
TEST@TGDB=> select 
  2     SYS_CONTEXT ('USERENV''SESSION_USER')||'_'||sys_context('USERENV','SID') ses_info
  3  from dual;
 
SES_INFO
--------------------------------------------------------------------------------
TEST_52
 
TEST@TGDB=> set termout on 
TEST@TGDB=> set sqlprompt '&sname>'
TEST_52>
 
TEST_52>
TEST_52>create table deadlock_1 ( id number, name varchar2(30));
 
Table created.
 
TEST_52> create table deadlock_2 ( id number, name varchar2(30));
 
Table created.
 
TEST_52>insert into deadlock_1 values ( 1'AAA');
 
1 row created.
 
TEST_52>insert into deadlock_2 values ( 2'BBB');
 
1 row created.
 
TEST_52>commit ;
 
Commit complete.
 
TEST_52>
 
 
SYS@TGDB=> conn test/test
Connected.
TEST@TGDB=> col ses_info new_value sname
TEST@TGDB=> set termout off
TEST@TGDB=> select 
  2     SYS_CONTEXT ('USERENV''SESSION_USER')||'_'||sys_context('USERENV','SID') ses_info
  3  from dual;
 
SES_INFO
--------------------------------------------------------------------------------
TEST_1
 
-- 테스트 세션 2(1)
TEST@TGDB=> set termout on 
TEST@TGDB=> set sqlprompt '&sname>'
TEST_1>
 
-- 테스트 세션 1(52) 업데이트 
TEST_52>update deadlock_1 set name ='SES1' where id = 1 ;
 
1 row updated.
 
TEST_52>
 
-- LOCK 체크 ( SID = 52 , DEADLOCK_1 , ROW LOCK )
SYS@TGDB=> set verify off
SYS@TGDB=> col owner format a15
SYS@TGDB=> col object_name format a30
SYS@TGDB=> col locked_mode format a15
SYS@TGDB=> 
SYS@TGDB=> select /*+ first_rows leading(l) use_nl(o) */
  2         session_id, process, owner, object_name, decode(locked_mode,1,'Null',2,'Row-S',3,'Row-x',4,'Share',5,'S/Row-X',6,'Exclusive','None') lock_mode
  3  from v$locked_object l, dba_objects o
  4  where l.object_id = o.object_id 
  5  /
 
SESSION_ID PROCESS                  OWNER           OBJECT_NAME                    LOCK_MODE
---------- ------------------------ --------------- ------------------------------ ---------
        52 5029                     TEST            DEADLOCK_1                     Row-x
 
SYS@TGDB=>
 
-- 테스트 세션 2(1) 업데이트 
TEST_1>update deadlock_2 set name ='SES2' where id = 2 ;
 
1 row updated.
 
TEST_1>
-- LOCK 체크 ( SID = 52 , DEADLOCK_1 , ROW LOCK )
-- LOCK 체크 ( SID =  1 , DEADLOCK_2 , ROW LOCK )
SYS@TGDB=> /
 
SESSION_ID PROCESS                  OWNER           OBJECT_NAME                    LOCK_MODE
---------- ------------------------ --------------- ------------------------------ ---------
         1 5045                     TEST            DEADLOCK_2                     Row-x
        52 5029                     TEST            DEADLOCK_1                     Row-x
 
SYS@TGDB=> 
 
-- 테스트 세션 1(52) 업데이트 ( 세션 2가 LOCK HOLD 상태인 ROW를 대상으로  ) 
TEST_52>update deadlock_2 set name ='SES1' where id = 2 ;
--> 대기 발생 
 
-- LOCK 체크 ( SID = 52 , DEADLOCK_1 , ROW LOCK )
-- LOCK 체크 ( SID =  1 , DEADLOCK_2 , ROW LOCK )
-- LOCK 체크 ( SID = 52 , DEADLOCK_2 , ROW LOCK ) << 추가됨, 대기 상태 
SYS@TGDB=> /
 
SESSION_ID PROCESS                  OWNER           OBJECT_NAME                    LOCK_MODE
---------- ------------------------ --------------- ------------------------------ ---------
         1 5045                     TEST            DEADLOCK_2                     Row-x
        52 5029                     TEST            DEADLOCK_2                     Row-x
        52 5029                     TEST            DEADLOCK_1                     Row-x
 
SYS@TGDB=> 
 
-- 테스트 세션 2(1) 업데이트 ( 세션 1가 LOCK HOLD 상태인 ROW를 대상으로  ) 
TEST_52>update deadlock_1 set name ='SES2' where id = 1 ;
--> 대기 발생 
 
TEST_52>update deadlock_2 set name ='SES1' where id = 2 ;
update deadlock_2 set name ='SES1' where id = 2
       *
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
 
 
TEST_52>
--> 테스트 세션 1(52)의 2번째 SQL 이 Cancel 된다 ( 주의 !! Rollback 이 아니다. )
 
 
<<Alert Log>>
Wed Mar 07 10:55:52 2018
ORA-00060: Deadlock detected. More info in file /u01/app/oracle/diag/rdbms/tgdb/TGDB/trace/TGDB_ora_5031.trc.
 
 
-- LOCK 체크 ( SID = 52 , DEADLOCK_1 , ROW LOCK )
-- LOCK 체크 ( SID =  1 , DEADLOCK_2 , ROW LOCK )
-- LOCK 체크 ( SID = 52 , DEADLOCK_2 , ROW LOCK ) << Cancel 됨 
-- LOCK 체크 ( SID =  1 , DEADLOCK_1 , ROW LOCK ) << 추가됨 
SYS@TGDB=> /
 
SESSION_ID PROCESS                  OWNER           OBJECT_NAME                    LOCK_MODE
---------- ------------------------ --------------- ------------------------------ ---------
         1 5045                     TEST            DEADLOCK_1                     Row-x
         1 5045                     TEST            DEADLOCK_2                     Row-x
        52 5029                     TEST            DEADLOCK_1                     Row-x
 
SYS@TGDB=>
 
-- 테스트 세션 2(1) 업데이트 ( 세션 1가 LOCK HOLD 상태인 ROW를 대상으로  ) 
TEST_1>update deadlock_1 set name ='SES2' where id = 1 ;
--> 대기 상태 유지됨 ( 테스트 세션 1 의 첫번 째 SQL 이 commit/rollback 전임 )
--> Deadlock(교착상태)라 해소 되지만, TX-LOCK 대기 상태가 발생함 
 
 
 
SYS@TGDB=> col w_sess for a50
SYS@TGDB=> col h_sess for a50
SYS@TGDB=> SELECT /*+ rule */ 
  2      sh.inst_id||' - '||sh.sid||' - '||decode(sh.status,'ACTIVE','A','I')||' : '||sh.event as H_Sess
  3    , sw.inst_id||' - '||sw.sid||' - '||decode(sw.status,'ACTIVE','A','I')||' : '||sw.event as W_Sess
  4    , lh.ctime  w_sec
  5  FROM
  6      gv$lock     lw
  7    , gv$lock     lh  
  8    , gv$session  sw
  9    , gv$session  sh
 10    , dba_objects ow
 11    WHERE 1 = 1
 12    AND   lh.id1        = lw.id1
 13    AND   lh.id2        = lw.id2
 14    AND   lh.request    = 0
 15    AND   lw.lmode      = 0
 16    AND (lh.id1, lh.id2) IN ( SELECT id1,id2
 17                              FROM   gv$lock
 18                              WHERE  request = 0
 19                              INTERSECT
 20                              SELECT id1,id2
 21                              FROM   gv$lock
 22                              WHERE  lmode = 0     )
 23    AND lw.inst_id = sw.inst_id
 24    AND lw.sid     = sw.sid
 25    AND lh.inst_id = sh.inst_id
 26    AND lh.sid     = sh.sid    
 27    AND sw.ROW_WAIT_OBJ# = ow.object_id(+
 28  ORDER BY
 29      w_sec desc 
 30  /
 
H_SESS                                             W_SESS                                                  W_SEC
-------------------------------------------------- -------------------------------------------------- ----------
1 - 52 - I : SQL*Net message from client           1 - 1 - A : enq: TX - row lock contention                1621
 
SYS@TGDB=> 
--> 테스트 세션 1(52) 이 Holder 이고, 테스트 세션 2(SID=1)은 대기 중으로 모니터링됨 
 
 -- 테스트 세션 1(52) ROLLBACK
 TEST_52>rollback ;
 
Rollback complete.
 
TEST_52>
 
-- 테스트 세션 2(1) UPDATE 수행 완료 
TEST_1>update deadlock_1 set name ='SES2' where id = 1 ;
 
 
1 row updated.
 
cs