Oracle数据库Oracle并发与⼀致性(附实例)
在单⽤户的数据库中,⽤户可以修改数据,⽽不⽤担⼼其他⽤户在同⼀时间修改相同的数据。但是在⼀个多⽤户的数据库中,多个事务内的语句可以同时更新相同的数据。注意,同时执⾏的多个事务必须产⽣有意义且⼀致的结果。
01
并发性与⼀致性
1.概念
在单⽤户的数据库中,⽤户可以修改数据,⽽不⽤担⼼其他⽤户在同⼀时间修改相同的数据。但是在⼀个多⽤户的数据库中,多个事务内的语句可以同时更新相同的数据。注意,同时执⾏的多个事务必须产⽣有意义且⼀致的结果。因此,多⽤户数据库必须提供以下两个功能。
数据并发性:确保多个⽤户可以同时访问数据。
数据⼀致性:确保每个⽤户看到数据的⼀致的视图,包括可以看到⽤户⾃⼰的事务所做的更改和其他⽤户已提交的事务所做的更改。
2.不⼀致性问题
并发会产⽣多个事务同时存取同⼀数据的情况。可能存取和存储不正确的数据,破坏事务的⼀致性和数据库的⼀致性。归纳起来共有以下3个主要问题。
(1)脏读:在事务中,读到了其他事务没有提交的记录,如图14-1所⽰。
图14-1 脏读现象
分析:
串⾏化结果:x:=140
并型:R1(a),W1(A),R2(A),ROLLBACK1,W2(A),COMMIT2
结果:x:=190 错误
问题:第4步,A2读了A1写后未提交的脏数据。
(2)不可重复读:在事务中,即使查询条件相同,下次返回的记录与上次返回记录也不⼀样,其不⼀样体现在记录被修改或记录被删除,如图14-2所⽰。
图14-2 不可重复读
分析:
串⾏化结果:X:=190
并⾏:R1(A),R2(A),S1(A),COMMIT,W2(A),COMMIT2。
结果,X:=140,错误。
问题:第2,6时间点,执⾏第6时间点前X已经不是第2时间点读出的100,已经是140了。A1对A2正在使⽤的记录数据做了修改。
区别:第2时间点中A2没有读A1修改但尚未提交的脏数据(不是脏读);第七时间点中A2没有写A1修改且尚未提交的脏数据(不是脏写)。
(3)幻影读:在事务中,即使查询条件相同,下次返回的记录与上次返回记录也不⼀样,其不⼀样体现在新增加了记录,如图14-3所⽰。
图14-3 幻影读
分析:
串⾏化结果:两个事务都满⾜规则,则返回YES。
并⾏:同⼀事物中相同的两次查询结果都⼀样,结果集记录的个数却增加⼀个。
Oracle中,使⽤谓词锁避免幻影读,即满⾜select语句中where谓词的记录都不能被insert,其他可以。
3.解决办法
要想解决脏读、不可重复读、幻影读等不⼀致的问题,就需要提⾼事务的隔离级别。
为了描述事务并发运⾏时的⼀致性⾏为,研究⼈员定义了⼀种事务隔离模型,称之为序列化(Serializability)。这种可串⾏化事务操作使得它看起来似乎没有其他⽤户在操作数据。虽然这种序列化机制在⼀般情况下是可⽤的,但在并发要求⾼的场景,它会严重影响系统的吞吐能⼒。即事务的隔离级别越⾼,并发能⼒也就越低。所以,⼀般情况下,需要在事务隔离级别与性能间进⾏取舍。
从运维的⾓度来看,提⾼事务隔离级别的解决办法可以总结如下所述。
(1)在通常情况下,程序员⽆须考虑每个事务内部的处理细节来避免并发异常,⽽是通过控制隔离级别来保证不出现
oracle数据库自动备份方法(1)在通常情况下,程序员⽆须考虑每个事务内部的处理细节来避免并发异常,⽽是通过控制隔离级别来保证不出现相关的异常。
(2)程序员可以采⽤以下两种办法尽量避免可能的并发错误。
使⽤尽量少的SQL,直接修改数据。
可以使⽤⼿动加锁等⽅式预先申请资源。
02
隔离机制
为了兼顾并发效率和异常控制,在标准SQL规范中,定义了如图14-4所⽰的四个事务隔离级别以及各隔离级别对各种异常的控制能⼒。
图14-4 事务隔离级别
Oracle数据库提供了Read committed(默认级别)和Serializable两种隔离级别,同时还⽀持只读模式。
1.Read Committed事务隔离级别
在此级别中,事务中查询到的数据都是在此查询前已经提交的。这种隔离级别避免了读取脏数据。
然⽽数据库并不阻⽌其他事务修改⼀个所读取的数据,其他事务可能在查询执⾏期间修改。
因此,⼀个事务运⾏同样的查询两次,可能发⽣不可重复读和幻影读的情况。
2.Serializable事务隔离级别
简单地说,Seriaizable就是使事务看起来像是⼀个接着⼀个地顺序地执⾏。
仅仅能看见在本事务开始前由其他事务提交的更改和在本事务中所做的更改。
保证不会出现⾮重复读和幻象。Seriaizable隔离级别提供了Read-Only事务所提供的读⼀致性(事务级的读⼀致性),同时⼜允许执⾏数据操纵类型的操作。
3.Read-Only事务隔离级别
只读隔离级别和序列化隔离级别很像,只是在只读事务中,除了⽤户sys外。不允许有修改操作,
因此只读事务不会有ORA-08177错误,只读事务在产⽣⼀个报告时很有效。
03
锁机制
事务之间的并发控制实际是通过锁实现的,锁是⽤来预防事务之间访问相同数据时的破坏性交互(如错误的更新数据等)的⼀种机制,在维护数据库并发性与⼀致性⽅⾯扮演了⼀个重要⾓⾊。
1.⾃动锁
Oracle数据库在执⾏SQL的时候会⾃动获取所需要的锁,因此⽤户在应⽤设计的时候只需要定义恰当的事务级别,不需要显⽰锁定任何资源。(即使Oracle提供了⼿动锁定数据的⽅法,⽤户不会⽤到。)
要显⽰锁定任何资源。(即使Oracle提供了⼿动锁定数据的⽅法,⽤户不会⽤到。)
2.Oracle锁模式
Oracle⾃动使⽤最低的限制级别去提供最⾼程度的并发。Oracle中有以下两种类型的锁。
(1)排他锁(X):这种类型是阻⽌资源共享的,⼀个事务获取了⼀个排他锁,则这个事务锁定期间只有这个事务可以修改这个资源。
(2)共享锁(S):这种类型是允许资源共享的,多个事务可以在同⼀资源上获取共享锁。
假设⼀个事务使⽤select ... for update(其他DML操作也⼀样)来选择表中的⼀⾏,则这个事务会获取该⾏的排他⾏锁以及所在表的共享表锁。
⾏锁允许其他事务修改除该⾏的其他⾏,⽽表锁阻⽌其他事务修改表结构。
3.Oracle封锁粒度
DML锁可以防⽌多个互相冲突的DDL,DML操作对数据的破坏性。DML语句⾃动获取两种类型的锁:Row locks(TX)和Table locks(TM),封锁粒度如图14-5所⽰。
图14-5 封锁粒度
4.意向锁
表是由⾏组成的,当向某个表加锁时,⼀⽅⾯需要检查该锁的申请是否与原有的表级锁相容;另⼀⽅⾯,还要检查该锁是否与表中的每⾏上的锁相容。
⽐如⼀个事务要在⼀个表上加S锁,如果表中的⼀⾏已被另外的事务加了X锁,那么该锁的申请也应被阻塞。
如果表中的数据很多,逐⾏检查锁标志的⼯作量将很⼤,系统的性能也会受到影响。
为了解决这个问题,可以在表级引⼊新的锁类型来表⽰其所属⾏的加锁情况,于是引出了“意向锁”的概念
意向锁的含义是如果对⼀个节点加意向锁,则说明该节点的下层节点正在被加锁;当对任⼀节点加锁时,必须先对它的上层节点加意向锁。
例如对表中的任⼀⾏加锁时,必须先对它所在的表加意向锁,然后再对该⾏加锁。
这样⼀来,当事务对表加锁时,就不再需要检查表中每⾏记录的锁标志位了,系统效率得以⼤⼤提⾼。
锁有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,这⾥的“=”指锁的强度相同)。
所谓锁的强度是指对其他锁的排斥程度。
这样⼜可以引⼊⼀种新的锁的类型——共享意向排它锁(SharedIntent Exclusive Lock,简称 SIX 锁):如果对⼀个数据库对象加 SIX 锁,表⽰对它加 S 锁,再加IX 锁,即 SIX=S+IX。
例如,若事务对某个表加 SIX 锁,则表⽰该事务要读整个表(所以要对该表加S 锁),同时会更新个别⾏(所以要对该表加 IX锁)。
这样数据库对象上所加的锁类型就可能有5 种:即S、X、IS、IX、SIX。
5.TM锁的相容矩阵
TM锁的相容矩阵如表14-1所⽰。
6.⼿⼯锁
Oracle数据库⾃动执⾏锁定,以确保数据并发性、数据完整性和与数据读取⼀致性。
但是也可以使⽤⼿动锁覆盖默认的锁机制。例如,事务中包含如下语句时会覆盖Oracle的默认锁:
settransaction isolation level
lock table,
< for update
04
项⽬案例
1
Read Commited隔离级别实例
事务1(可以是Read committed或Serializable)与事务2(Read Committed)的典型交互,称之为Lost Update(丢失更新),具体如下操作步骤所⽰。
2
Serializable事务隔离级别实例
下⾯所⽰是⼀个序列化事务是如何与其他事务交互的。
如果⼀个序列化任务不去尝试修改其他事务在序列化事务开始后提交的数据,那么Serialized Access问题就可以避免

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。