谈谈Oracle中的锁

1.数据库较之excel之类的东西最大的一个不同,就是支持并发.而锁,则是实现数据库并发控制的一个非常重要的技术.对于一张表来说,它分为两部分,一部分是数据,一部分是它的元数据(也就是我们平时说说的相关数据字典),我们在删除表(drop table)截断表(truncate table)的时候是没有删除数据的,是修改数据字典,也就是元数据.
所以我们保护一张表,既要保护数据,又要保护元数据.因此,锁可以分为保护元数据的锁--TM锁,和保护数据的锁--TX (表级锁和行级锁).

2.oracle提供的所类型可以根据v$lock_type 中的type来查询,我们平时接触的最多的是两种

select * from v$lock_type where type in ('TM','TX')

根据查询的结果:

查看描述,可以大概的得知两种锁的信息.TM是同步访问对象用的,TX是和事务有关的.

3.要知道的有2个概念:

(1).锁定数据的锁,也就是行级锁,只有一种:排它锁 exclusive (ROW)
(2).锁定表上的锁,即锁定元数据的锁 metadata(table),一共有5种:

2 RS: row share
3 RX: row exclusive
4 S: share
5 SRX: share row exclusive
6 X: exclusive

4.根据oracle联机文档的concepts的第13章的一个表

我们可以从这个表找出至少2个东西,.第一是每种数据库操作都对应的是什么样的锁(参考中间那一列),第二是每种锁之间,如果遇到之后是否会产生冲突,所谓冲突就是是否会使当前的数据库操作夯住.其中Y*,表示如果两个操作锁定的是同一行,那么就会有冲突,后操作的会等待前一个操作完成之后再完成,否则会一直夯在那儿;如果不为同一行,那么则不会冲突,后操作的不会等待.举一个例子来说明:假设现在A操作为:对id=1的记录进行update,而B操作为:对id=2的记录进行删除,根据表格说明,在A上操作时在TM级别的锁会是RX,TX级别只有一个是X,在B上会有一个TM级别的锁会是RX,TX级别只有一个X,而根据表格说明,当RX遇到RX的时候,如果2个操作非同一条记录,那么则不会冲突,故AB两个操作均会按照各自的先加一个TM锁,再加一个TX锁,再顺利执行各自的操作,不会夯住。如果将B操作的记录id换位1,那么两个操作记录为同一条记录,在TM锁上会表现出冲突,所以B操作就会等待A操作完成提交后(也就是A的TX锁释放了后),B再相应的生成一个TX锁和一个TM锁再完成操作,否则的话会一直夯住,等待A释放TX锁.

5.常用的动态性能视图:

select * from v$lock_type where type in ('TM','TX');
select * from v$lock;
select * from v$transaction;

重点说明一下v$lock视图:

先设置一个场景:在session A中对一个表的记录进行更新,更新完后并不提交,在session B中对改表的同一条记录进行删除

Session A:
SQL> create table ttt as select * from dba_objects where rownum<=10;

表已创建。

SQL> update ttt set object_name='TEST' where object_id=20;

已更新 1 行。

SQL>

Session B:
SQL> delete from ttt where object_id=20;

此时因为A并没有提交,所以B会一直夯住

再打开一个session C,查询相关的v$lock视图

SQL> select * from v$lock where type in ('TM','TX');

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
CA4244F4 CA424508        147 TX     393242        563          0          6        270          0
C8E7F704 C8E7F71C        140 TM      55156          0          3          0        301          0
C8E7F7C8 C8E7F7E0        147 TM      55156          0          3          0        270          0
C8ED3C38 C8ED3D54        140 TX     393242        563          6          0        301          1

可以很清晰的看到2个sid产生了锁.对于sid为140的session,产生了一个TM和一个TX锁,TM的锁模式(LMODE)=3,(3为RX: row exclusive和表格对照相符,当操作为update的时候,产生RX锁);对于sid为147的session,也产生了一个TM和一个TX锁,TM的锁模式(LMODE)=3 (3为RX: row exclusive和表格对照相符,当操作为delete的时候,产生RX锁),而TX的锁模式(LMODE)=0,代表正在等待一个锁.从v$lock_type的定义上面,我们也可以看出,type为TM的锁,ID1表示的是object_id,查询dba_objects可以很容易的得出锁定的对象是TTT这个obj. 从最后一列BLOCK(该block并不代表块,而是代表阻塞)=1也可以看出,sid=140的session在生成TX锁之后,发现之后一个的操作也是修改该条记录,所以BLOCK+1,表示阻塞其他的操作同时操作这条记录.

另外,此时,查询select * from v$transaction;视图,也可以得到相关联的信息

我们从v$lock_type对TX锁的描述,可以知道TX是和事务有关的.因此查看之前v$lock上TX锁的相关信息,可以看到ADDR的值与v$transaction的值是一样的.甚至可以根据ID1的值来计算,锁定的是哪个段:根据TX的ID1去除以和取余2的16次方,得到相关信息:

SQL> select 393242 / 65536, mod(393242, 65536) from dual;

393242/65536 MOD(393242,65536)
------------ -----------------
  6.00039673                26

可以神奇的发现和v$transaction中的XIDUSN和XIDSLOT对应上了!

6.最后补充一个操作,创建索引的时候会生成的锁操作:

首先将ttt表插入很多数据
SQL> insert into ttt select * from dba_objects;
SQL> commit;

提交完成。

SQL> select count(*) from ttt;

  COUNT(*)
----------
   1739045

接着再在改表上创建一个索引
SQL> create index idx_ttt on ttt(object_id);

创建索引的同时,查询v$lock表

可以发现在创建索引的会生成2个TM锁,锁类别分别为4和3,我们查询这2个TM分别锁定的是什么对象:

根据查询结果发现lmode=4的object_id为55160的对象对应的是TTT这个表,LMODE=4对应的是TM的S锁,我们得出这样一个结论:当对表进行创建索引操作时,会伴随出现LMODE=4的S锁.根据上面的各种操作所对应的锁的表格,发现S锁和任何dml操作都是冲突的!我们对此就要非常注意了,尤其是在生产上,当在一个很大的表上进行索引创建的时候,任何对该表的DML操作都会被夯住!!!


7.ORACLE的锁是block里面实现的,SQLSERVER,DB2是内存里面实现的.内存实现有资源消耗问题,当内存不足会引发锁升级,但是ORACLE不会发生锁升级.

原文地址:https://www.cnblogs.com/nazeebodan/p/2696124.html