您的位置:首页 > 数据库 > Oracle

<<Oracle数据库性能优化艺术(第五期)>> 第2周 锁

2014-02-16 14:14 393 查看
1.分别模拟insert,update和delete造成阻塞的示例,并对v$lock中的相应的信息进行说明,给出SQL演示。
1.1 insert:
SQL> select distinct sid from v$mystat;

SID
----------
373

SQL> drop table t;

Table dropped.

SQL> create table t (id int primary key);

Table created.

SQL> insert into t values(1);

1 row created.

SQL>
======================================
SQL> select distinct sid from v$mystat;

SID
----------
272

SQL> select * from t;

no rows selected

SQL> insert into t values(1);

--session272在这里卡住
======================================
v$lock信息:
SQL> select * from v$lock where sid in (373,272) order by sid desc;

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000DBD6BBC0 00000000DBD6BC38 373 TX 327694 3198697 6 0 133 1
00000000DD1A7DE0 00000000DD1A7E38 373 AE 3269431 0 4 0 909 0
00007FA8635EC088 00007FA8635EC0E8 373 TM 3321815 0 3 0 133 0
00000000DD1A9178 00000000DD1A91D0 373 TO 3290249 1 3 0 881 0
00007FA8635EC088 00007FA8635EC0E8 272 TM 3321815 0 3 0 106 0
00000000DBDB30F8 00000000DBDB3170 272 TX 458754 2502943 6 0 106 0
00000000DD1AA798 00000000DD1AA7F0 272 AE 3269431 0 4 0 264 0
00000000DD1AAD48 00000000DD1AADA0 272 TX 327694 3198697 0 4 106 0

8 rows selected.

SQL>

1.2 update:

SQL> select * from t;

ID
----------
1

SQL> select distinct sid from v$mystat;

SID
----------
209

SQL> select * from t;

ID
----------
1

SQL> update t set id=2 where id=1;

1 row updated.

SQL>
======================================
SQL> select distinct sid from v$mystat;

SID
----------
202

SQL> update t set id=3 where id=1;

--session202卡住
======================================

v$lock信息:

SQL> select * from v$lock where sid in (209,202) order by sid desc;

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000DD1A7DE0 00000000DD1A7E38 209 AE 3269431 0 4 0 200 0
00007F0617F77AE0 00007F0617F77B40 209 TM 3321815 0 3 0 85 0
00000000DBD20C68 00000000DBD20CE0 209 TX 327696 3198961 6 0 85 1
00007F0617F77AE0 00007F0617F77B40 202 TM 3321815 0 3 0 70 0
00000000DD1A9178 00000000DD1A91D0 202 AE 3269431 0 4 0 194 0
00000000DD1AA798 00000000DD1AA7F0 202 TX 327696 3198961 0 6 70 0

6 rows selected.

SQL>

1.3 delete:

SQL> select distinct sid from v$mystat;

SID
----------
209

SQL> select * from t;

ID
----------
1

SQL> delete from t where id=1;

1 row deleted.

SQL>
======================================
SQL> select distinct sid from v$mystat;

SID
----------
202

SQL> delete from t where id=1;
--session 202 卡住
======================================

v$lock信息:

SQL> select * from v$lock where sid in (209,202) order by sid desc;

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000DD1A7DE0 00000000DD1A7E38 209 AE 3269431 0 4 0 438 0
00007F0617F76AA8 00007F0617F76B08 209 TM 3321815 0 3 0 66 0
00000000DBD20C68 00000000DBD20CE0 209 TX 196626 3278256 6 0 66 1
00007F0617F76AA8 00007F0617F76B08 202 TM 3321815 0 3 0 56 0
00000000DD1A9178 00000000DD1A91D0 202 AE 3269431 0 4 0 432 0
00000000DD1AA798 00000000DD1AA7F0 202 TX 196626 3278256 0 6 56 0

6 rows selected.

SQL>

--EOF--

2.模拟RI锁定导致阻塞的场景,并分析v$lock相应的锁定信息,给出SQL演示。
=============================================
测试主表增删改:
SQL> create table p(id int primary key);

Table created.

SQL> create table c(id references p(id));

Table created.

SQL> insert into p values(1);

1 row created.

SQL> insert into p values(2);

1 row created.

SQL> insert into c values(1);

1 row created.

SQL> commit;

Commit complete.

SQL> insert into c values(3);
insert into c values(3)
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.SYS_C0013952) violated - parent key not
found

SQL> insert into p values(3);

1 row created.

SQL> select distinct sid from v$mystat;

SID
----------
34

SQL> set linesize 200
SQL> select * from v$lock where sid in (34);

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000718597E8 0000000071859840 34 AE 100 0 4 0 150 0
000000007185A290 000000007185A2E8 34 TO 65927 1 3 0 132 0
00007F799CA040B8 00007F799CA04118 34 TM 77329 0 3 0 42 0
00007F799CA040B8 00007F799CA04118 34 TM 77331 0 3 0 42 0

0000000070AC9830 0000000070AC98A8 34 TX 131076 1103 6 0 42 0

SQL> rollback;

Rollback complete.

SQL> update p set id=3 where id=1;
update p set id=3 where id=1
*
ERROR at line 1:
ORA-02292: integrity constraint (SYSTEM.SYS_C0013952) violated - child record found

SQL> update p set id=3 where id=2;

1 row updated.

SQL> select * from v$lock where sid in (34);

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000718597E8 0000000071859840 34 AE 100 0 4 0 200 0
000000007185A290 000000007185A2E8 34 TO 65927 1 3 0 182 0
00007F799C61C260 00007F799C61C2C0 34 TM 77329 0 3 0 4 0
0000000070AC9830 0000000070AC98A8 34 TX 262161 825 6 0 4 0

SQL> rollback;

Rollback complete.

SQL> delete from p where id=2;

1 row deleted.

SQL> select * from v$lock where sid in (34);

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000718597E8 0000000071859840 34 AE 100 0 4 0 221 0
000000007185A290 000000007185A2E8 34 TO 65927 1 3 0 203 0
00007F799C61C260 00007F799C61C2C0 34 TM 77329 0 3 0 2 0
0000000070AC9830 0000000070AC98A8 34 TX 458773 903 6 0 2 0

SQL> rollback;

Rollback complete.
=============================================
测试从表增删改:
SQL> insert into c values(2);

1 row created.

SQL> select * from v$lock where sid in (34);

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000718597E8 0000000071859840 34 AE 100 0 4 0 237 0
000000007185A290 000000007185A2E8 34 TO 65927 1 3 0 219 0
00007F799C61C260 00007F799C61C2C0 34 TM 77329 0 3 0 3 0
00007F799C61C260 00007F799C61C2C0 34 TM 77331 0 3 0 3 0

0000000070AC9830 0000000070AC98A8 34 TX 393240 1124 6 0 3 0

SQL> rollback;

Rollback complete.

SQL> update c set id=2 where id=1;

1 row updated.

SQL> select * from v$lock where sid in (34);

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000718597E8 0000000071859840 34 AE 100 0 4 0 261 0
000000007185A290 000000007185A2E8 34 TO 65927 1 3 0 243 0
00007F799C61C260 00007F799C61C2C0 34 TM 77329 0 3 0 2 0
00007F799C61C260 00007F799C61C2C0 34 TM 77331 0 3 0 2 0

0000000070AC9830 0000000070AC98A8 34 TX 327706 1270 6 0 2 0

SQL> rollback;

Rollback complete.

SQL> delete from c where id=1;

1 row deleted.

SQL> select * from v$lock where sid in (34);

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000718597E8 0000000071859840 34 AE 100 0 4 0 275 0
000000007185A290 000000007185A2E8 34 TO 65927 1 3 0 257 0
00007F799C61C260 00007F799C61C2C0 34 TM 77329 0 3 0 2 0
00007F799C61C260 00007F799C61C2C0 34 TM 77331 0 3 0 2 0

0000000070AC9830 0000000070AC98A8 34 TX 589856 1104 6 0 2 0

SQL> rollback;

Rollback complete.

SQL>

可见,在主表上操作时,只有insert才会在从表上加一个row exclusive(3)锁;
而在从表上操作时,无论insert/update/delete都会在主表上加一个row exclusive(3)锁.

--EOF--

3.自己构想一个使用手工锁定解决一种业务需求的场景,并给出SQL演示。
模拟订票流程,手工锁定已查询出来的票
SQL> drop table tickets purge;

Table dropped.

SQL> create table tickets(id int primary key, price int);

Table created.

SQL> insert into tickets values(1,100);

1 row created.

SQL> insert into tickets values(2,200);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from tickets where id=1 for update;

ID PRICE
---------- ----------
1 100

SQL>

=======================================
SQL> select * from tickets where id=1;

ID PRICE
---------- ----------
1 100

SQL> select * from tickets where id=1 for update nowait;
select * from tickets where id=1 for update nowait
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

SQL>

--EOF--

4.给出从mode 2-6 的TM锁相互间的互斥示例。
session=209,LMODE=2
SQL> select distinct sid from v$mystat;

SID
----------
209

SQL> lock table t in row share mode;

Table(s) Locked.

SQL>
=======================================
session=373,LMODE=3
SQL> select distinct sid from v$mystat;

SID
----------
373
SQL> lock table t in row exclusive mode;

Table(s) Locked.

SQL>
=======================================
session=272,LMODE=4
SQL> select distinct sid from v$mystat;

SID
----------
272

SQL> lock table t in share mode;
--卡住
=======================================
session=231,LMODE=5
SQL> select distinct sid from v$mystat;

SID
----------
231

SQL> lock table t in share row exclusive mode;
--卡住
=======================================
session=202,LMODE=6
SQL> select distinct sid from v$mystat;

SID
----------
202

SQL> lock table t in exclusive mode;
--卡住
=======================================
查询v$lock发现row share(2)/row exclusive(3)阻塞了share(4)/share row exclusive(5)/exclusive(6)
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where sid in (209,373,272,231,202) and type = 'TM';

SID TY ID1 ID2 LMODE REQUEST BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
209 TM 3321898 0 2 0 1
373 TM 3321898 0 3 0 1
272 TM 3321898 0 0 4 0
231 TM 3321898 0 0 5 0
202 TM 3321898 0 0 6 0

SQL>

参考资料:
Automatic Locks in DML Operations http://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm
lockmode Clause

Specify one of the following modes:

ROW SHARE ROW SHARE permits concurrent access to the locked table but prohibits users from locking the entire table for exclusive access. ROW SHARE is synonymous with SHARE UPDATE, which is included for compatibility with earlier versions of Oracle Database.

ROW EXCLUSIVE ROW EXCLUSIVE is the same as ROW SHARE, but it also prohibits locking in SHARE mode. ROW EXCLUSIVE locks are automatically obtained when updating, inserting, or deleting.

SHARE UPDATE See ROW SHARE.

SHARE SHARE permits concurrent queries but prohibits updates to the locked table.

SHARE ROW EXCLUSIVE SHARE ROW EXCLUSIVE is used to look at a whole table and to allow others to look at rows in the table but to prohibit others from locking the table in SHARE mode or from updating rows.

EXCLUSIVE EXCLUSIVE permits queries on the locked table but prohibits any other activity on it.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_9015.htm
--EOF--

5.给出一个导致死锁的SQL示例。
session1:
SQL> select * from t;

ID
----------
1
2

SQL> update t set id=10 where id=1;

1 row updated.
=======================================
session2:
SQL> update t set id=20 where id=2;

1 row updated.
=======================================
session1:
SQL> update t set id=10 where id=2;

--卡住
=======================================
session2:
SQL> update t set id=20 where id=1;

--卡住
=======================================
session1报死锁错:
SQL> update t set id=10 where id=2;
update t set id=10 where id=2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource

SQL>
=======================================
session2:SQL> update t set id=20 where id=1;

--继续卡住

--EOF--
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐