度量快速开发平台-专业、快速的软件定制快开平台

标题: ORACLE的行锁的实现 [打印本页]

作者: 张兴康    时间: 2020-4-9 17:45
标题: ORACLE的行锁的实现
在执行包含update,delete,merge,select for update语句时事务必须得到一个TX锁,也就是事务锁。而且会持有这个所直到提交或回滚。事务未提交时,为了实现事务一致性,其它事务不能访问正在修改的数据,其它事务必须排队等待这个事务提交或回滚。下面先介绍排队的实现。
    当事务锁住某些数据时,其它事务必须排队等待,ORACLE在SGA中分配的Reource Structure、Lock Structure数据结构通过Enqueue算法实现。

    Resource Structure有三个与并发控制有关的成员:Owner,Waiter,Converter。它们其实是指向Lock Structure链表的指针。分别表示已经获取资料访问权的进程、等待进程、锁转换等待进程。资源由ID1,ID2标识,在上图中 TM表示资源类型,256表示dba_objects中的objectid
    Lock Structure用于记录访问共享资源的数据结构,它记录了锁模式、进程ID等信息 。当一个进程访问共享资源时,必须要去锁定该资源,所以它先要从内存中申请一个Lock Structure, 然后根据封锁是否成功 加入不同的链表。
[size=11.6667px]    行级锁:事务会定位到修改的数据在哪个block,哪个行,然后检查行的LB(Lock Byte锁标识位)
tl: 73 fb: --H-FL-- lb: 0x1  cc: 12 (lb=0x1说明编号0x1的ITL代表的事务锁住本行)
锁标识位指向的ITL(Interested Transaction List,直译过来就是感兴趣的事物列表。也 就是对该数据块产生影响的事务。它包含了事务的信息:ITL序号、事务编号、回滚段地址、事务标识、锁定的行数、SCN/FSC。)

Itl           Xid                                             Uba                                         Flag                Lck        Scn/Fsc
0x01   0x0006.011.000004c7  0x00c001fd.0105.13    ----     1  fsc 0x0000.00000000
检查ITL对应的事务的状态是不是active ,如果是则把这个Lock Structure挂到Resource Structure的Waiter链表中 。

    如果LB指向ITL对应的事务状态不是active,则将Lock Structure挂到Resource Structure的Owner链表,然后在回滚段中获得一个事务槽、分配空间,创建数据的前镜像,然后到块头申请ITL表项,并修改block的itl Lck标志位,修改记录lb标志位指向事务所在的itl。事务结束时,将会去检查Waiter和Conversion 链表,Conversion链表优先,将锁分配给最先进入队列的请求者。
[size=11.6667px]下面修改表中的数据,不提交,然后DUMP数据块,查看DUMP中的ITL和行的LB
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

/*设置跟踪文件的标识符,方便查找*/
SQL> alter session set tracefile_identifier='dump';

Session altered.
/*查找行的文件号和块号*/
SQL> select dbms_rowid.rowid_relative_fno(rowid)file_id,dbms_rowid.rowid_block_number(rowid)block_id from department where depid='D2285';

   FILE_ID   BLOCK_ID
---------- ----------
         7        1259[size=11.6667px]
SQL> update department set note='lock test' where depid='D2285';
1 row updated

SQL> alter system dump datafile 7 block 1259;

System altered./*下面是DUMP内容,省略部分内容*/
Block header dump:  0x01c004eb
Object id on Block? Y
seg/obj: 0x12333  csc: 0x00.f765d1  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x1c004e8 ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                                  Uba                         Flag  Lck        Scn/Fsc
0x01   0x0006.011.000004c7  0x00c001fd.0105.13    ----     1  fsc 0x0000.00000000
0x02   0x0005.016.000003f5   0x00c006a0.0131.2a  C---   0  scn 0x0000.00f76566
bdba: 0x01c004eb
data_block_dump,data header at 0xfffffd7ffcb84a64

block_row_dump:
tab 0, row 0, @0x2e7
tl: 73 fb: --H-FL-- lb: 0x1  cc: 12
col  0: [ 5]  44 32 32 38 35
col  1: [ 6]  cf af bd a8 b3 c9
col  2: *NULL*
col  3: [ 6]  d2 b5 ce f1 b2 bf
col  4: [ 5]  30 30 31 32 33
col  5: [ 9]  64 75 6d 70 20 74 65 73 74
col  6: [11]  78 6d 09 1c 10 34 0d 08 76 bf 80
col  7: [ 5]  46 61 6c 73 65
col  8: [ 4]  58 41 30 31
col  9: [ 5]  44 32 32 38 35
col 10: *NULL*
col 11: [ 2]  30 31
tab 0, row 1, @0x378
tl: 64 fb: --H-FL-- lb: 0x0  cc: 12
col  0: [ 5]  44 32 32 38 36
col  1: [ 6]  cf af bd a8 b3 c9
col  2: *NULL*

    到这里我们可以发现,ORACLE的行级锁 只是数据块头的ITL、数据行头的LB锁标识位,不需要消耗额外的资源。 需要注意的是事务并不是被行阻塞,而是被其它的事务阻塞  ,  会话通过上述的字段检测是否被阻塞达到锁的效果。  Lock Structure 可以理解为一个session,如果第一行的 封锁都用resource 、lock两种数据结构那内存需求和维护开销将是一个噩梦。 所以某些数据库就有锁升级机制,而ORACLE没有。

作者: 张兴康    时间: 2020-4-9 17:46

作者: caixuqad    时间: 2020-4-9 17:53

作者: 张兴康    时间: 2020-4-9 17:54
caixuqad 发表于 2017-5-9 17:53

换个头像多好
作者: caixuqad    时间: 2020-4-12 17:42

作者: caixuqad    时间: 2020-4-23 19:25

作者: 张兴康    时间: 2020-4-23 20:13





欢迎光临 度量快速开发平台-专业、快速的软件定制快开平台 (http://plat.delit.cn/) Powered by Discuz! X3.2