Oracle的TX锁(行级锁、事务锁)

问题:如何使用事务? 回答:一共有三步。 一、先开启事务。 [color=red]•在Oracle中,事务是在上一次事务结束之后,数据“第一次”被修改时自动开启。 •在java中,设置链接为手动提交模式开始。代码: connection.setAutoCommit(false)。[/color] 二、进行(屡次)数据操做(增删改)…… 三、结束事务: commit、rollback。 问题:如何结束事务? 回答: 有两种方法: 一、确认对数据的修改:提交,commit。 二、撤消对数据的修改:回滚,rollback。 另外,当Oracle系统或者PL/SQL脚本抛出异常,都会形成数据回滚。 问题:什么是提交模式,与事务有什么关系? 回答: [color=red]提交模式有两种: 自动提交:在每一次数据被修改之后,自动提交。这种模式下是没法支持事务的。 手动提交:全部的数据修改都在内存中,当执行commit时才一块儿提交。只要有一条sql执行失败,则全部的sql自动回滚。只能在手动提交模式下才能使用事务。[/color] 3.1 Oracle的TX锁(行级锁、事务锁) [color=red]许多对Oracle不太了解的技术人员可能会觉得每个TX锁表明一条被封锁的数据行,其实否则。TX的本义是Transaction(事务),当一个事务第一次执行数据更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE语句进行查询时,它即得到一个TX(事务)锁,直至该事务结束(执行COMMIT或ROLLBACK操做)时,该锁才被释放。因此,一个TX锁,能够对应多个被该事务锁定的数据行(在咱们用的时候可能是启动一个事务,而后SELECT… FOR UPDATE NOWAIT)。[/color] 在Oracle的每行数据上,都有一个标志位来表示该行数据是否被锁定。Oracle不像DB2那样,创建一个链表来维护每一行被加锁的数据,这样就大大减少了行级锁的维护开销,也在很大程度上避免了相似DB2使用行级锁时常常发生的锁数量不够而进行锁升级的状况。数据行上的锁标志一旦被置位,就代表该行数据被加X锁,Oracle在数据行上没有S锁。 3.2 TM锁(表级锁) 3.2.1 意向锁的引出 表是由行组成的,当咱们向某个表加锁时,一方面须要检查该锁的申请是否与原有的表级锁相容;另外一方面,还要检查该锁是否与表中的每一行上的锁相容。好比一个事务要在一个表上加S锁,若是表中的一行已被另外的事务加了X锁,那么该锁的申请也应被阻塞。若是表中的数据不少,逐行检查锁标志的开销将很大,系统的性能将会受到影响。为了解决这个问题,能够在表级引入新的锁类型来表示其所属行的加锁状况,这就引出了"意向锁"的概念。 意向锁的含义是若是对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任一结点加锁时,必须先对它的上层结点加意向锁。如:对表中的任一行加锁时,必须先对它所在的表加意向锁,而后再对该行加锁。这样一来,事务对表加锁时,就再也不须要检查表中每行记录的锁标志位了,系统效率得以大大提升。 3.2.2 意向锁的类型 由两种基本的锁类型(S锁、X锁),能够天然地派生出两种意向锁: 意向共享锁(Intent Share Lock,简称IS锁):若是要对一个数据库对象加S锁,首先要对其上级结点加IS锁,表示它的后裔结点拟(意向)加S锁; 意向排它锁(Intent Exclusive Lock,简称IX锁):若是要对一个数据库对象加X锁,首先要对其上级结点加IX锁,表示它的后裔结点拟(意向)加X锁。 另外,基本的锁类型(S、X)与意向锁类型(IS、IX)之间还能够组合出新的锁类型,理论上能够组合出4种,即:S+IS,S+IX,X+IS,X+IX,但稍加分析不难看出,实际上只有S+IX有新的意义,其它三种组合都没有使锁的强度获得提升(即:S+IS=S,X+IS=X,X+IX=X,这里的"="指锁的强度相同)。所谓锁的强度是指对其它锁的排斥程度。 这样咱们又能够引入一种新的锁的类型: 共享意向排它锁(Shared Intent Exclusive Lock,简称SIX锁):若是对一个数据库对象加SIX锁,表示对它加S锁,再加IX锁,即SIX=S+IX。例如:事务对某个表加SIX锁,则表示该事务要读整个表(因此要对该表加S锁),同时会更新个别行(因此要对该表加IX锁)。 这样数据库对象上所加的锁类型就可能有5种:即S、X、IS、IX、SIX。 具备意向锁的多粒度封锁方法中任意事务T要对一个数据库对象加锁,必须先对它的上层结点加意向锁。申请封锁时应按自上而下的次序进行;释放封锁时则应按自下而上的次序进行;具备意向锁的多粒度封锁方法提升了系统的并发度,减小了加锁和解锁的开销。 3.3 Oracle的TM锁(表级锁) Oracle的DML锁(数据锁)正是采用了上面提到的多粒度封锁方法,其行级锁虽然只有一种(即X锁),但其TM锁(表级锁)类型共有5种,分别称为共享锁(S锁)、排它锁(X锁)、行级共享锁(RS锁)、行级排它锁(RX锁)、共享行级排它锁(SRX锁),与上面提到的S、X、IS、IX、SIX相对应。须要注意的是,因为Oracle在行级只提供X锁,因此与RS锁(经过SELECT … FOR UPDATE语句得到)对应的行级锁也是X锁(可是该行数据实际上尚未被修改),这与理论上的IS锁是有区别的。 锁的兼容性是指当一个应用程序在表(行)上加上某种锁后,其余应用程序是否可以在表(行)上加上相应的锁,若是可以加上,说明这两种锁是兼容的,不然说明这两种锁不兼容,不能对同一数据对象并发存取。 下表为Oracle数据库TM锁的兼容矩阵(Y=Yes,表示兼容的请求; N=No,表示不兼容的请求;-表示没有加锁请求): 表五:Oracle数据库TM锁的相容矩阵 一方面,当Oracle执行SELECT…FOR UPDATE、INSERT、UPDATE、DELETE等DML语句时,系统自动在所要操做的表上申请表级RS锁(SELECT…FOR UPDATE)或RX锁(INSERT、UPDATE、DELETE),当表级锁得到后,系统再自动申请TX锁,并将实际锁定的数据行的锁标志位置位(指向该TX锁);另外一方面,程序或操做人员也能够经过LOCK TABLE语句来指定得到某种类型的TM锁。下表是笔者总结了Oracle中各SQL语句产生TM锁的状况: SQL语句 [color=darkred] 表锁模式 容许的锁模式[/color] Select * from table_name…… 无 RS、RX、S、SRX、X Insert into table_name…… RX RS、RX Update table_name…… RX RS、RX Delete from table_name…… RX RS、RX Select * from table_name for update RS RS、RX、S、SRX lock table table_name in row share mode RS RS、RX、S、SRX lock table table_name in row exclusive mode RX RS、RX lock table table_name in share mode S RS、S lock table table_name in share row exclusive mode SRX RS lock table table_name in exclusive mode X 无 表六:Oracle数据库TM锁小结 咱们能够看到,一般的DML操做(SELECT…FOR UPDATE、INSERT、UPDATE、DELETE),在表级得到的只是意向锁(RS或RX),其真正的封锁粒度仍是在行级;另外,Oracle数据库的一个显著特色是,在缺省状况下,单纯地读数据(SELECT)并不加锁,Oracle经过回滚段(Rollback segment)来保证用户不读"脏"数据。这些都提升了系统的并发程度。 因为意向锁及数据行上锁标志位的引入,减少了Oracle维护行级锁的开销,这些技术的应用使Oracle可以高效地处理高度并发的事务请求。