oracle并行 锁,oracle的锁和并行机制

锁是并发访问的时候用于保护不共享资源不被同时并发修改的机制。

oracle锁分为DML锁,DDL锁,内部锁和latch

DML锁确保一次只能只有一个人修改某一行(TX锁),而且正在处理一个表时别人不能删除(TM锁)。

DDL锁,在DDL操作是系统会自动为对象加上DDL锁,保护这些对象不被其他会话锁修改。

latch是轻量级的串行化设备,用于协调对共享数据结构、对象、文件的多用户访问,一般都是保护共享内存结构使用的锁,在此不做讨论。

一般的锁管理器工作过程:

1.找到想要锁定的那一行地址

2.在锁管理器排队

3.锁定列表

4.搜索列表,查看别人是否锁定这一行

5.在列表中创建一个新的条目,表明已经锁定这一行

6.对列表解锁

接下里修改,之后提交修改后,继续过程:

7.再次排队

8.锁住锁的列表

9.在这个列表中锁定,并释放所有的锁

10.对列表解锁

oracle锁管理方式:

找到需要锁定的那行地址

到达那一行

锁定这一行

通常lock有三个组件:Resource Structure(资源)、Lock Structure(锁)和Enqueue(排队机制)

Resource和lock是数据结构,而Enqueue是算法。

Resource Structure每一个需要并发控制的资源都有用这个数据结构来描述,先关的成员为:owner、waiter和converter,这是三个指针,分别指向3个由Lock Structure组成的链表。

Lock Structure

每当进程需要访问共享资源时,必须先“锁定”该资源,这个动作实际上是从内存中申请一个Lock Structure,

,在其中记录“锁模式、进程ID”等重要信息。然后看是否立即能够获得资源的访问权,如果不能的话将这个Lock structure挂到Resource Structure的Waiter链表中,如果能够获得,则把Lock Structure的owner链表中。

最常用的锁模式

Share 拥有这对资源进行只读访问,允许其他用户并发只读访问

Exclusive 拥有者对资源进行修改访问,不允许其他用户并发访问

Enqueue 算法

Lock使用的是Enqueue算法,可以理解为“先入先出队列”,如果进程的锁定请求不能满足,该进程的Lock Structure就被加到Waiter链表的末端。当占用进程释放锁时,会检查Waiter和Converter队列,把锁分配给先入对的请求者。 converter和waiter两个等待队列,算法的有些区别:如果某个操作先后需要2中不同模式的锁,比如先是share mode然后是exclusive mode,则进程会先请求share mode 后获得lock structure会挂在owner队列上,当需要exclusive mode锁时,进程先释放share mode的锁,然后再次申请exclusive mode的锁,但是可能无法立即获得,这时请求会挂在converter队列下,converter队列会被优先于waiter队列处理。

oracle行级锁机制

首先明白三个概念:

ITL:每个数据块的头部有一个叫做ITL的数据结构,用于记录那些事务修改了这个数据块的内容。

记录头ITL索引:每条记录的记录头部有一个字段,用于记录ITL表项号,可以看做指向ITL表的指针

TX锁,事务锁

TM锁:保护表或视图定义不被修改的锁

当一个事务开始时,必须申请一个TX锁,这种锁保护资源是回滚段、回滚段数据块,因此这个这个申请意味着:用户进程必须先申请到回滚段资源后才能开始一个事务,才能执行DML语句修改数据。

申请到回滚段资源后,用户事务就可以开始修改数据了,事务信息可在v$transaction中查到,在修改数据表的记录时,需要遵守如下操作顺序:

首先获得这个表的TM锁,这个锁用于保护事务执行过程中其他用户不能修改表结构;

事务修改某个数据块记录时,首先需要在改数据块块头的ITL表中申请一个空闲表项,并在其中记录事务号,实际就是在记录这个事物要使用的回滚段地址;

事务修改该数据块的某条记录时,会设置该记录头部的ITL索引指向上一步申请到的表项,然后再修改记录内容,修改前先在回滚段对记录修改前的状态做一个拷 贝,然后才能修改数据记录,这个拷贝用于以后的回滚、恢复和一致性读。当其他用户并发修改这条记录时,会根据记录头的ITL索引读取ITL表项内容,查看 这个事务是否已经提交,如果没有提交,则这个用户的TX锁会等待前一个用户的TX锁的释放。

例如如下式转储的一个数据块的ITL信息:

Block header dump:  0×00411819

Object id on Block? Y

seg/obj: 0×10396  csc: 0×00.d62e7  itc: 2  flg: O  typ: 1 – DATA

fsl: 0  fnx: 0×0 ver: 0×01

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0×01   0×0008.00b.0000029b  0x00c05271.006a.3c  —-    3  fsc 0×0000.00000000

0×02   0×0000.000.00000000  0×00000000.0000.00  —-    0  fsc 0×0000.00000000

seg/obj:seg/obj id

csc:clean scn

itc:itl slots的个数,此时多少个事务在对本data block进行操作

flg: 0=on the freelist

typ:数据块类型

fsl: itl tx freelist slot

fnx: dba of next block on freelist

Itl:interested transaction list index

Xid:transaction id

Uba:undo address

Flag:事务状态标志

Lck:事物所影响行的数量

oracle 在对数据行锁定时,行指向事务ID的一个副本,事务ID存储在包含数据的块中,释放锁时,事务ID会保存下来,这个事务ID时事务特有的,表示了回滚段 号、槽和序列号,事务ID留在包含数据行的块中,可以告诉其他会话:一个会话拥有这个数据行。另一个会话会看到锁ID,由于锁ID表示一个事务,所以可以 很快的查看持有这个锁的事务是否活动的。如果锁不活动的,则允许会话访问这个数据,如果锁还是活动的,会话会要求一旦释放锁就得到通知。所以这需要一个排 队机制:请求锁的会话会排队,等待目前拥有这个锁的事务执行,然后的到这个数据。可以根据v$lock视图的lmode和request mode判断谁是owner、waiter和converter

owner:lomode>0,request=0

waiter:lmode=0,request>0

converter:lmode>0,request>0

例如下试验可以清楚看到这些信息:

系统已更改。

SQL> create table t1 ( x int );

表已创建。

SQL> create table t2 ( x int );

表已创建。

SQL> insert into t1 values ( 1 );

已创建 1 行。

SQL> insert into t2 values ( 1 );

已创建 1 行。

SQL> select (select username

2                 from v$session

3                 where sid = v$lock.sid) username,

4         sid,

5         id1,

6         id2,

7         lmode,

8         request, block, v$lock.type

9    from v$lock

10   where sid = (select sid

11                  from v$mystat

12                 where rownum=1)

13  /

USERNAME  SID   ID1   ID2   LMODE  REQUEST    BLOCK    TYPE

——– —–  —-   —-  —–   ——-   —–    —-

SYS       13    66455   0     3        0         0      TM

SYS       13    66456   0     3        0         0      TM

SYS       13    589840  662   6        0         0      TX

SQL> select object_name, object_id

2    from user_objects

3   where object_name in (‘T1′,’T2′)

4  /

OBJECT_NAME    OBJECT_ID

————  ———

T1            66455

T2            66456

每个事务只能有一个TX锁,但是TM锁依照修改的对象个数而定,TM对应的ID1列就是DML锁定对象ID.

SQL> select username,

2         v$lock.sid,

3         trunc(id1/power(2,16)) rbs,

4         bitand(id1,to_number(‘ffff’,'xxxx’))+0 slot,

5         id2 seq,

6         lmode,

7         request

8  from v$lock, v$session

9  where v$lock.type = ‘TX’

10    and v$lock.sid = v$session.sid

11    and v$session.username = USER;

USERNAME  SID    RBS    SLOT   SEQ   LMODE  REQUEST

——– —– ——  —–  —— —— ———

SYS       13     9      16      662       6     0

SQL> select XIDUSN, XIDSLOT, XIDSQN  from v$transaction;

XIDUSN    XIDSLOT     XIDSQN

—— ———- ———-

9         16        662

oracle事务不同于其他数据库之处,不需要专门语句显示开始事务,事务会在修改数据的第一条语句处开始,但是一定要用commit或rollback事务。

oracle的commit做了如下操作:

为事务生成一个SCN

LGWR将所有余下的缓存重做日志条目写至磁盘,并把SCN记录到在线重做日志文件中

v$lock中记录着会话持有的锁,这些锁将被释放,而排队等待这些锁的每一个队列都会被唤醒

如果事务处理的某些块还在缓存中,则会快速的模式访问并清除

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0×01   0×0008.00b.0000029b  0x00c05271.006a.3c  C—    0  scn 0×0000.000d6470

0×02   0×0005.007.00000372  0x00c0dbca.006e.2f  –U-    1  fsc 0×0000.000d6584

如上的flag列,第一条ITL信息显示数据块当前事务信息已经被清除,第二个还未清除事务ITL信息标志为U;

oracle并发支持,实现了一种多版本体系,能够同时物化多个版本的数据,能够提供读一致性机制,数据读取器绝不会被写入器所阻塞,也就是写不会阻塞读。一种情况例外,那就是在分布式事务处理(2PC)期间。

另外,记住大多数DDL都带排它锁,有些DDL没有DDL锁,如create index idx on t(x) online;online关键字会改变建立索引的方法。oracle只会得到表上的TM锁,防止其他DDL发生,但是运行DML运行。oracle发生 死锁的原因外键未加索引、位图索引发生更新,外键未加索引更新或删除父表都会对整个子表加锁

会话1:

create table p ( x int primary key );

create table c ( x references p );

insert into p values ( 1 );

insert into p values ( 2 );

commit;

insert into c values ( 2 );

会话2:

delete from p where x = 1;;

这个时候机会发生阻塞:

SQL> select

2        (select username from v$session where sid=a.sid) blocker,

3         a.sid,

4        ‘ is blocking ‘,

5         (select username from v$session where sid=b.sid) blockee,

6             b.sid

7    from v$lock a, v$lock b

8   where a.block = 1

9     and b.request > 0

10     and a.id1 = b.id1

11     and a.id2 = b.id2;

BLOCKER    SID ‘ISBLOCKING’  BLOCKEE     SID

——-  —–  ———   ——— ——-

SYS       142  is blocking  SYS          13

不需要对外键加索引的情况:

1、没有从父表删除行

2、没有更新父表的唯一键/主键值

3、没有从父表联结子表

参考:

TOM oracle 9i&10g编程艺术

摘自我的blog:ww.manotes.net

©著作权归作者所有:来自51CTO博客作者marvelyu的原创作品,如需转载,请注明出处,否则将追究法律责任

oracle职场休闲Oracle

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值