ITPub博客

首页 > 数据库 > Oracle > 锁机制

锁机制

Oracle 作者:410192979 时间:2016-03-22 18:28:48 0 删除 编辑
1.oracle锁机制主要用于管理对共享资源的并发访问,同时保证数据完整性和一致性。(其中完整性的一个体现例子为外键未加索引,修改父表会锁定整个字表)
2.常见DML阻塞语句:INSERT/UPDATE/DELETE/MERGE/SELECT FOR UPDATE
3.锁行为
     只有当行记录正在被修改时,该记录才会被锁定;    
     当某行记录正在被修改,会阻塞其他进程的写操作;
     oracle的写入不会阻塞读(通过undo实现);
     oracle的读取不会阻塞写(select ... for update除外);
4.锁分为共享锁和排他锁
     获得资源排他锁的事务,会阻止该资源被共享,即只有占有排他锁的事务可以对该资源有使用权限;
     获得资源共享锁的事务,允许该资源被共享,但是会阻止想要以排它锁占有该资源的会话;
     例如,会话A需要修改表T中的一行记录,则会话A会给该记录上的排它锁,获取整张表的共享锁。这样,其他会话可以对A事务修改记录以外的所有记录进行操作。但是如果会话C想要修改表结构,即需要获取表T的排他锁,则此时是不允许的,原因为会话A持有表T的共享锁。
     注意:上例中是会话之间的关系!因为如果在同一个会话中,执行DDL,会自动提交之前的update操作,释放表T上的共享锁。
5.锁转换和锁升级
     oracle只有在必要的时候进行锁转换,从来不进行锁升级。
     锁转换是在同样的锁定粒度大小下,将锁的限制等级升级;锁升级是在同样的限制等级下,将锁定的粒度加大。
     oracle从来不会进行锁升级,因为锁升级极大的增加了发生死锁的可能性。例如,事务1和事务2都需要进行锁升级,并且俩事务都是因为相同的资源而发生了等待,这样造成了死锁。
6.锁的持续时间
     oracle在事务不再需要资源时,例如回滚或者提交,会自动释放锁。通常情况下,在整个事务期间内,事务都会持有事务相关的锁。这些锁阻止了脏读、更新丢失和破坏性的DDL的发生。
     注意:对子表的全表锁是发生在主表的语句级别,而不是事务级别。甚至使用DBMS_LOCK可以人为的释放和分配锁,甚至锁可以跨事务。
     oracle事务在回滚或者提交时,会释放事务内的锁资源。
     当然,当事务回滚到某个检查点,则检查点之后所需要的锁资源也会被释放。但是,每个事务只有在不再等待之前的资源时,才可以获取当前可用的资源。当前等待的事务只有在原始事务回滚或者提交时,才会停止等待。
7.锁和死锁
     oracle会自动检测死锁,并且在语句级进行死锁的回滚。
     oracle的死锁主要发生在明确的覆盖了默认的锁机制,虽然oracle并不会升级锁,也不使用查询锁,但是使用了记录级别(row-level)的锁,所以死锁还是会偶尔发生。
8.自动锁
     oracle会代替事务自动的对资源进行锁定,组织其他事务以排他锁的形式来访问相同资源。根据资源的不同和对资源所做的操作的不同,数据库需要不同的锁和不同的限制等级。
     oracle锁分为以下类别
自动锁类别
描述
DML锁
用于保护数据,例如表锁用于保护整张表,行锁用于锁定指定的行。
DDL锁
保护方案对象的结构,例如表或视图的数据字典定义。
system锁
保护数据库内部结构,例如数据文件、latches、mutexes和内部锁。
9.DML锁
     DML锁包括行锁(TX)和表锁(TM):
     TX锁主要是由于DML操作(insert/delete/update/merge/select ... for update)语句引起的行锁,行锁是最小粒度的排他锁,保证了并发性和吞吐量。
     行锁(TX)和并发性:当不同会话对同一张表的不同记录做修改,且均未提交,则每个会话只能看到自己会话内所做的修改,不能看到其他未提交会话所做的修改,这样提高了事务的并发性。
     行锁(TX)的存储:oracle将锁的信息存储在数据块头部(有些数据库通过锁管理器在内存中管理锁);oracle数据库通过队列机制来分配行锁资源,当一个事务需要锁定一条未被锁定的记录,则该事务会在该记录所在数据块头部放一个锁(包含事务ID等相关信息),这样所有被该事务修改的数据记录,都会指向数据块头部存储的事务ID(transaction ID);当事务结束的时候,事务ID(transaction ID)仍然留在数据块头部,如果其他会话想要修改该数据块的某条记录,会根据里面存储的事务ID来判断其想要修改的记录是否被其他锁给锁定了,若想要修改的记录被锁定,则需要等待锁定记录的事务结束后,再进行事务的处理。若想要修改的记录没有被锁定,则直接获取该记录的行锁(TX)。
     表级锁(TM)主要是由于在表级发生的insert/update/delete/merge/select...for update/lock table操作语句而产生的。DML操作需要表级锁来代替事务预留对于表的DML操作,并且防止与事务冲突的DDL操作。
     表级锁有以下模式:
     Row Share(RS):最低限制级别的表锁,提供最高级别的并发性。
     Row Exclusive Table Lock(RX):允许多事务同时获取SX锁
     Share Table Lock(S):允许多事务同时持有S锁,且允许多事务同时进行查询(select ... for update除外)但是想要更新内容,前提为只有一个事务持有S锁。
     Share Row Exclusive Table lock(SRX):在某个时间点只允许一个事务持有SRX锁,允许其他事务来对表进行查询(select ... for update除外),但是不允许进行update更新。
     Exclusive Table lock(X):最高级别的限制,获取X锁后,不允许其他事务在该表上进行任何类型的DML操作。
     表级锁和外键:
     当对父表的键值(主键或唯一键)进行更新时,对于子表的锁定行为取决于自表的外键是否建了索引:
     第一、如果子表外键没有建索引,则子表会频繁的被锁定,更容易发生死锁。所以存在外键的表必须在外键上建索引,除非父表中的键值永远也不会发生更新。 注意:子表中的DML操作不会对父表产生锁定。
     第二、如果子表外键建了索引,则对父表中对应键值的修改不会要求对子表进行锁定。
10.DDL(data dictionary lock)锁
     当使用DDL进行方案对象的定义进行操作时,DDL锁会对语句中涉及到的对象进行锁定,需要注意的是,oracle绝对不会对整个数据字典进行锁定!
     当DDL语句执行时,oracle会自动的替DDL事务分配数据字典锁。用户不能够显式的申请数据字典锁。例如,当用户创建一个存储过程,则创建存储过程中涉及到的方案对象的数据字典信息都会被锁定,防止被破坏,直到存储过程结束后,释放相应数据字典锁。
     排他数据字典锁:该锁会阻止其他会话获得DDL或者DML锁。也就是说,在有事务持有DDL锁时,无法对表结构定义进行修改,也无法对表中的数据进行修改,只允许查询。
     共享数据字典锁:该锁允许多事务同时持有,但是持有的事务不能够对相关联的方案对象定义进行修改。但是允许对数据内容进行修改。
     可中断解析锁:这些锁允许一个对象向另外某个对象注册其依赖性。
11.系统锁
     闩:闩是一种低级的串行化设备,用于协调对共享数据结构、对象和文件的多用户访问。主要用于保护一下场景中的数据结构:
     1.多个会话的并发修改;
     2.当一个会话在修改某数据结构时,允许另一会话进行读取;
     3.当处理数据结构时,进行内存回收。
     一般来说,一个闩会对SGA中的多个对象进行保护。
     互斥锁:互斥锁是一种防止对象在多进程并发访问的时候从内存中老化或者被破坏的一种低级机制。
     互斥锁的好处:互斥锁有可能减轻竞争压力;互斥锁比闩消耗更少的内存;在共享模式,互斥锁允许多会话的并发。
12.内部锁
     内部锁是高级的、复杂的且服务于多种目的的一种锁机制。
     oracle内部锁主要包括:数据字典缓存锁、文件和日志管理锁和表空间和undo段锁
13.人工锁
     人工锁主要应用场景:应用要求事务级别的读一致性或者可重复读;应用要求事务以排他形式来访问资源,这样事务就不需要等待其他事务完成。
     oracle支持手工修改系统默认自动锁:
     在会话级别,可以通过alter session来修改;
     在事务级别,可以通过set transaction isolation level语句;lock table/view语句;select ... for update 三条语句来修改。
     用户自定义锁:通过DBMS_LOCK包来实现。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26366371/viewspace-2061985/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
王燕辉! 一个80后的IT从业者! 紧跟时代最前沿技术!

注册时间:2014-03-08

  • 博文量
    154
  • 访问量
    140596