锁是并发访问的时候用于保护不共享资源不被同时并发修改的机制。
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: 0x10396  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
0x01   0×0008.00b.0000029b  0x00c05271.006a.3c  —-    3  fsc 0×0000.00000000
0x02   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
0x01   0×0008.00b.0000029b  0x00c05271.006a.3c  C—    0  scn 0×0000.000d6470
0x02   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编程艺术

oracle的锁与并发机制的更多相关文章

  1. ORACLE的锁机制

    数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性. 加锁是实现数据 ...

  2. 第二十节: 深入理解并发机制以及解决方案(锁机制、EF自有机制、队列模式等)

    一. 理解并发机制 1. 什么是并发,并发与多线程有什么关系? ①. 先从广义上来说,或者从实际场景上来说. 高并发通常是海量用户同时访问(比如:12306买票.淘宝的双十一抢购),如果把一个用户看做 ...

  3. oracle 事务 锁机制

    原文地址:http://www.cnblogs.com/quanweiru/archive/2013/05/24/3097367.html 本课内容属于Oracle高级课程范畴,内容略微偏向理论性,但 ...

  4. Java 并发机制底层实现 —— volatile 原理、synchronize 锁优化机制

    本书部分摘自<Java 并发编程的艺术> 概述 相信大家都很熟悉如何使用 Java 编写处理并发的代码,也知道 Java 代码在编译后变成 Class 字节码,字节码被类加载器加载到 JV ...

  5. 从浅到深掌握Oracle的锁

      1.分别模拟insert,update和delete造成阻塞的示例,并对v$lock中的相应的信息进行说明,给 出SQL演示. Insert示例 会话:SQL> select * from ...

  6. [数据库锁机制] 深入理解乐观锁、悲观锁以及CAS乐观锁的实现机制原理分析

    前言: 在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念.数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务 ...

  7. sqlserver 并发机制

    一.事务四大属性 分别是原子性.一致性.隔离性.持久性. 1.原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库, ...

  8. Oracle关于锁的几种类型和参数

    设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据的一致性和准确性.Oracle数据库封锁方式有三种:共享封锁,独占封锁,共享更新封锁 封锁类型 Oracle RDBMS的封锁类型可分 ...

  9. Oracle的锁

    Oracle数据库中的锁机制 数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数 ...

随机推荐

  1. Unity脚本执行顺序自研框架

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/52372611 作者:car ...

  2. mysql破解密码安装与基本管理

    一.MySQL介绍 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是 ...

  3. Python框架之Django学习笔记(十)

    又是一周周末,如约学习Django框架.在上一次,介绍了MVC开发模式以及Django自己的MVT开发模式,此次,就从数据处理层Model谈起. 数据库配置 首先,我们需要做些初始配置:我们需要告诉D ...

  4. ADO之密码验证--3次错误就锁定『改进』

    这里使用了SqlHelper,简化程序 自己写一个SqlHelper,把数据库的连接等都写到里面去. 首先把连接字符串添加到配置文件里去,右键解决方案-->添加新建项-->选择应用程序配置 ...

  5. Python 拓展之推导式

    写在之前 推导式是从一个或多个迭代器快速简洁的创建数据结构的一种办法,它可以将循环和条件判断结合,从而可以避免语法冗长的代码. 列表推导式 我在之前的文章中(零基础学习 Python 之 for 循环 ...

  6. BZOJ 4590 [Shoi2015]自动刷题机 ——二分答案

    二分答案水题. #include <cstdio> #include <cstring> #include <iostream> #include <algo ...

  7. BZOJ 3509 [CodeChef] COUNTARI ——分块 FFT

    分块大法好. 块内暴力,块外FFT. 弃疗了,抄SX队长$silvernebula$的代码 #include <map> #include <cmath> #include & ...

  8. 几种API接口

    实用号码归属地查询(IP 地址,手机号码): 默认格式: http://api.liqwei.com/location/ (使用来访者的 IP 地址) 指定 IP 地址格式: http://api.l ...

  9. eclspse魔板

    window->prefence->搜索 template即可

  10. shell的使用

    删除 http://blog.csdn.net/u011579204/article/details/46709929 #! /bin/bash dir=/webserver/test/(等号之间不能 ...