事务隔离

引自:http://blog.csdn.net/turkeyzhou/article/details/7636165

1      什么是事务

1.1 我们为什么需要事务

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关 操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、 一致性、隔离性和持久性)属性。

上面的解释和描述来自百度百科(http://baike.baidu.com/view/1298364.htm),我们为什么需要事务,通俗点说,就是需要“一组操作或者行为,要么全成功,要么全失败,一荣俱荣,一辱俱辱”。

1.2 事务ACID属性

事务的特性可以定义为四种属性:ACID(atomicity,consistency,isolation,durability)。

l   atomicity:原子性,在一个事务中的所有操作,相当于一个原子操作,要么全部成功,要么全部失败。

l   consistency:一致性,就是在事务执行前后,对于事务本身的用意而言,数据库中的数据是保持一致的,数据库的一致性是建立在原子性的基础之上的,更多的由编码的程序员保证,最经典的案例是A,B帐号之间的转账。

在整个过程中,对于一致性的定义是AB的账户总额保持事务前后一致,而次数是通过事务的原子性以及事务定义的编码共同来实现的(如果你本意是转账,A减去50而B加上100则不符合一致性本意)。

另一方面则表示,一致性状态表示只有合法的数据才能被写入数据库,如果事务执行的某些操作,违反了数据的一致性规则,则
事务会rollback到之前数据一致的状态,另一方面,如果事务执行成功,则会将数据状态从事务执行前的符合数据一致性规则的一种状态,变迁到事务执行
后的另一种数据符合一致性规则的状态。(Definition: Consistency

states that only valid data will be written to thedatabase. If, for
some reason, a transaction is executed that violates thedatabase’s
consistency rules, the entire transaction will be rolled back andthe
database will be restored to a state consistent with
those rules. On theother hand, if a transaction successfully executes,
it will take the databasefrom one state that is consistent with the
rules to another state that is alsoconsistent with the rules.)

l   isolation:隔离性,事务的隔离性是指事务和事务之间的数据可见性,这也是本文需要详细介绍的地方。数据库定义了各种隔离级别,以在并发性和数据完整性中权衡。

l   durability:持久性,事务完成以后,所有的数据都将持久到数据库中,不会因为其他原因而丢失。

2      事务隔离

2.1       事务同时读写所带来的问题

事务的隔离性是指当多个事务并发同时执行的时候,数据的可见性不同而导致的一些问题,主要问题包括如下四种:

l   更新丢失(同时更新);

当两个事务同时对一条数据进行更新的时候,因为执行顺序交叉,在没有协同的情况,可能导致某一个事务的更新被覆盖,我们称之为更新丢失(这在银行转账中是十分危险和不可接受的)。

l   脏读;

顾名思义,脏读,未提交读,均是指事务在同事读写的过程中间,一个事务读取到另一个事务没有commit的更新,此时,这个更新是否会被正式提交,或者发生异常回滚是不可预料的,所以可以认定此时所读取到的数据为脏数据。

l   不可重复读

不可重复读取主要是因为在一次事务中多次读取某条记录,但因为其他事务的介入,而导致多次读取的值不一致。

l   幻读;

幻读主要在事务A中读取记录数为N条,而事务B插入一条,则事务A再次读取时则变成了N+1条。

3      数据库锁

3.1       锁的类型

如同线程一样,数据库也用锁来保证事务之间的协同工作,在数据库中,锁分为共享锁和排他锁,顾名思义,多个共享锁可以共存,而排它锁则是独占锁,共享锁也称之为读锁,而排它锁也称之为独占锁,写锁。

l  排他锁 被加锁的对象只能被持有锁的事务读取和修改,其他事务无法在该对象上加其他锁,也不能读取和修改该对象

l  共享锁 被加锁的对象可以被持锁事务读取,但是不能被修改,其他事务也可以在上面再加共享锁。

特别的,对共享锁: 如果两个事务对同一个资源上了共享锁,事务A 想更新该数据,那么它必须等待 事务B 释放其共享锁。

3.2       锁粒度

锁的范围和粒度可以分为表锁和行锁,其中表锁为数据库实现,而行锁则由存储引擎实现(如innodb引擎)。

3.3       封锁协议(Locking Protocol)

在运用锁来进行事务之间的协议时,还必须基于一定的规则,如何时加锁,何时释放锁,加锁的粒度以及等等。这些称之为封锁协议,不同的封锁协议定义了不同的隔离级别。不同的隔离级别则解决了之前事务协作锁带来的问题,以便服务在吞吐量和并发性以及事务完整性之间做出权衡。

4      事务隔离级别

针对事务协作锁带来的四大问题,于是根据不同的封锁协议,制定了事务间的隔离级别。其实本质上均是通过锁来干涉事务之间的执行顺序。

4.1       事务协作问题原因极其分析

l   丢失更新

原因:读锁可以共享,而记录常驻内存。

解决方式:读锁升级为独占锁,或者重复读取,cas更新。

l   脏读

执行场景(顺序):事务A在事务B更新数据和回滚过程中间读取记录。

解决方式:当事务B更新数据的时候禁止其他事务对记录进行读取。

加锁方式:事务B将写锁(独占锁)保持到事务结束。

l   不可重复读

执行场景(顺序):事务A第一次读取数据在事务B更新数据并提交之前,第二次读取数据在事务B更新记录并提交之后,导致同一次事务中多次读取同一记录不同。

解决方式:事务A在读取数据和提交事务之间不允许其他事务对数据进行修改。

加锁方式:事务A持有共享锁直至事务结束。

l   幻读

解决方式:数据库将行锁升级为表锁;

4.2       隔离级别及对应封锁规则

l  read uncommitted(一级封锁规则)

表示可以接受读取未提交的数据(脏读)。封锁规则为:当事务修改记录时,为记录添加共享锁直至事务结束,在次过程中,其他事务可以读取和更新数据。因此此种隔离级别会带来丢失更新,脏读,重复读,幻读各种问题。

l  read commited(二次封锁规则)

表示允许读取提交后的数据,意思是允许(不可重复读)现象,但拒绝脏读。

封锁规则为对应的脏读解决方案,事务将写锁(独占锁)保持到事务结束,而读取数据的时候当读取操作完毕则立即释放读锁。

执行顺序会变成:

l  repeatable read(三级封锁协议)

表示可以重复读(意思为不允许不可重复读,真纠结)。封锁规则为,保持共享锁到事务结束。

但因为是行锁,无法避免幻读,另外因为事务读锁可以并存,那是否repeatable read在应对丢失更新的情况方面表现如何呢?

你会发现,因为共享锁和排他锁的释放周期均被放大,导致了资源的死锁,数据库如何解决这种死锁状况呢?如SQL
Server在处理这种情况时则是引入了Update锁,当读取数据的时候为记录上获取Update锁,哪个事务先修改,则将锁升级为独占锁从而对该数据
进行修改。而mysql innodb则主要是通过两方面来处理死锁问题:

n   死锁检测;当发现死锁时,将一个事务回退(回滚拥有最少排他行级锁的事务,一种对最易回滚事务的大致估算),令一个事务获得锁完成事务,但是innodb也无法检测所有死锁的问题。

n   死锁超时;可以通过设置innodb_lock_wait_timeout来设置获取锁而等待的超时时间。

l  Serialization(四级封锁)

直接对 事务中 所 读取 或者 更改的数据所在的表加表锁,也就是说,其他事务不能 读写 该表中的任何数据。这样所有的 脏读,不可重复读,幻读 ,都得以避免。

5      MySql事务隔离级别设置

在mysql中,可以通过如下命令查询当前事务隔离级别:

[email protected]@global.tx_isolation;  //全局        

                    [email protected]@tx_isolation;//当前会话

设置会话级别分别为:

setglobal transaction isolation level read committed;

setsession transaction isolation level read committed;

时间: 2024-12-14 14:56:15

事务隔离的相关文章

MySQL的事务与事务隔离

MySQL中自从引入InnoDB引擎后,在MySQL中就支持事务,事务就是一组原子性的查询语句,也即将多个查询当作一个独立的工作单元,平时通过提交工作单元来完成在事务中的相应的查询或修改,在能支持事务的数据库中必须要满足ACID测试,即事务的四个特性: A:Atomicity,原子性(都执行或者都不执行) C:Consistency,一致性(从一个一致性状态转到另外一个一致性状态) I:Isolaction,隔离性(一个事务的所有修改操作在提交前对其他事务时不可见的) D: Durability

数据库事务的四大特性和事务隔离级别

Reference: [1] http://www.cnblogs.com/fjdingsd/p/5273008.html [2] http://blog.csdn.net/fg2006/article/details/6937413 数据库事务四大特性 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全

数据库事务隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committed.Repeatable read.Serializable,这四个级别可以逐个解决脏读.不可重复读.幻读这几类问题. √: 可能出现    ×: 不会出现   脏读 不可重复读 幻读 Read uncommitted √ √ √ Read committed × √ √ Repeatable read × × √ Serializable × × × 注意:我们讨论隔离级别的场景,主要是在多个

<事务隔离性>

Overview 事务的隔离性是指在并发环境中,并发的事务是隔离的.一个事务的执行不能被其他事务干扰. 也即,不同的事务并发操作相同数据时,每个事务都有各自完整的数据空间. 隔离性 在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同,包括: 未授权读取,也称为读未提交(Read Uncommitted).该级别允许脏读取,其隔离级别最低.[关于脏读,幻读,blabla...请往下拉].如果一个事务正在处理某一数据,并对其进行了更新,但同时尚未完成事务,因此还未进行事务提交

MySQL事务隔离级别详解

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销.Read Uncommitted(读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取未提交的数据,也被称之为脏读(Dirty Read).Read Committed(读取提交内容) 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的).

Spring五个事务隔离级别和七个事务传播行为

1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据. 2. 不可重复读 :是指在一个事务内,多次读同一数据.在这个事务还没有结束时,另外一个事务也访问该同一数据.那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的.这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读.例如,一个编辑人员两次读取同一文档,但在两次读取之间

Innodb中的事务隔离级别和锁的关系

前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. #一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道

事务隔离级别与阻塞

本篇文章参考<Microsoft SQL Server企业级平台管理实践>中第9章和第10章 阻塞与死锁未提交读(read uncommitted)指定语句可以读取已由其他事务修改但尚未提交的行.也就是说,允许脏读.未提交读的意思也就是,读的时候不申请共享锁.所以它不会被其他人的排他锁阻塞,它也不会阻塞别人申请排他锁.SELECT * FROM TABLE WITH(NOLOCK)已提交读(read committed)--防脏读指定语句不能读取已由其他事务修改但尚未提交的数据.这样可以避免脏

事务隔离级别,操作

然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. 2 [mysqld] 3 transaction-isolation = REPEATABLE-READ 这里全局默认是REPEATABLE-READ,其实MySQL本来默认也是这个级别 2.对当前session修改,在登录mysql客户端后,执行命令: 要记

数据库的事务隔离机制

事务隔离级别:一个事务对数据库的修改与并行的另一个事务的隔离程度. 两个并发事务同时访问数据库表相同的行时,这些问题可以归结为5类: 3类数据读问题(脏读.不可重复读和幻象读) 2类数据更新问题(第一类丢失更新和第二类丢失更新). 1.幻读:事务T1读取一条指定where条件的语句,返回结果集.此时事务T2插入一行新记录,恰好满足T1的where条件.然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想. 2.不可重复读取:事务T1读取一行记录,紧接着事务T2修改了