【综合】事务的处理及隔离级别

原文地址:http://blog.csdn.net/qiaoge134/article/details/20031949

事务的隔离级别:

先说说 (通俗说)

1. 脏读:是一个事务读取了  其他事务没有提交的数据。

2.不可重复度:就是第一次读和第二次读,两次读到的 数据不一致,原因是:在此期间有其他的事务修改了数据。

3.幻读:就是第一次读和第二次读,两次读到的 数据不一致,

原因是:在此期间有事务插入了新的数据(区别于不可重复读:不可重复读是  对于修改操作而言,幻读对插入造作而言)

事务的隔离级别有:read-uncommite(读没提交),read-commite(读已提交),none-repeatedRead(不可重复度),serializable(序列化,顺序化)

一般的  数据库都不存在  第一种read-uncommite的情况。

一般数据库都有自己默认的事务隔离级别;一般情况是  read-commite,这个解决了脏读的问题,并且效率高 。

人们为了让  数据库的效率高并且可以隔离级别高,就出来了  “乐观锁”和“悲观锁”的思想。

简单理解:乐观锁:当一个事务读取数据后,要进行操作,在操作前  为数据加一个版本信息(version),当在操作期间有其他事物对改数据进行了操作,那么版本信息就会变

化,这样当改事务执行结束后判断一下版本信息,如果没变,那么提交事务,如果改变了,那么重复执行上述操作---这就是乐观锁的思想,很多地方用到这个思想,比如安卓的

数据库sqlite就又到了version。

悲观锁:是当一个事务对  数据进行操作的时候对数据加“锁”,在此事务没有提交之前,其他事务是不能操作该数据的,只有这个事务结束提交后,其他事物才能对它进行操作。

当然,很明显,乐观锁的性能要优于悲观锁。。。

原文地址:http://blog.sina.com.cn/s/blog_4c197d420101awhc.html

关于MySQL的事务处理及隔离级别

事务是DBMS得执行单位。它由有限得数据库操作序列组成得。但不是任意得数据库操作序列都能成为事务。一般来说,事务是必须满足4个条件(ACID)

原子性(Autmic):事务在执行性,要做到“要么不做,要么全做!”,就是说不允许事务部分得执行。即使因为故障而使事务不能完成,在rollback时也要消除对数据库得影响!

一致性(Consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变!

隔离性(Isolation):如果多个事务并发执行,应像各个事务独立执行一样!

持久性(Durability):事务提交后被持久化到数据库.

MYSQL的事务处理主要有两种方法。

1、用BEGIN,ROLLBACK,COMMIT来实现

开始:START TRANSACTION或BEGIN语句可以开始一项新的事务

提交:COMMIT可以提交当前事务,是变更成为永久变更

回滚:ROLLBACK可以回滚当前事务,取消其变更

2、直接用set来改变mysql的自动提交模式

MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!

我们可以通过set autocommit=0 禁止自动提交

set autocommit=1 开启自动提交

来实现事务的处理。

但注意当你用 set autocommit=0 的时候,你以后所有的SQL都将做为事务处理,直到你用commit确认或rollback结束,并且只用于当前连接。

※ MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持!

自己的理解(关于脏读,不可重复读,幻读)

※脏读:一个事务读取了另一个未提交的并行事务写的数据。

(事务T1更新了一行记录的内容,但是并没有提交所做的修改。事务T2读取更新后的行,然后T1执行回滚操作,取消了刚才所做的修改。现在T2所读取的行就无效了。)

exp:

小明的分数为89,事务A中把他的分数改为98,但事务A尚未提交。

与此同时,

事务B正在读取小明的分数,读取到小明的分数为98。

随后,

事务A发生异常,而回滚了事务。小明的分数又回滚为89。

最后,

事务B读取到的小明的分数为98的数据即为脏数据,事务B做了一次脏读。

(大部分数据库缺省的事物隔离级别都不会出现这种状况)

※不可重复读:一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过。

(事务T1读取一行记录,紧接着事务T2修改了T1刚才读取的那一行记录。然后T1又再次读取这行记录,发现与刚才读取的结果不同。这就称为“不可重复”读,因为T1原来读取的那行记录已经发生了变化。)

exp:

在事务A中,读取到小明的分数为89,操作没有完成,事务还没提交。

与此同时,

事务B把小明的分数改为98,并提交了事务。

随后,

在事务A中,再次读取小明的分数,此时工资变为98。在一个事务中前后两次读取的结果并不致,导致了不可重复读。

※幻读:一个事务重新执行一个查询,返回一套符合查询条件的行,发现这些行因为其他最近提交的事务而发生了改变。

(事务T1读取一条指定的WHERE子句所返回的结果集。然后事务T2新插入 一行记录,这行记录恰好可以满足T1所使用的查询条件中的WHERE 子句的条件。然后T1又使用相同的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突 然出现的一样。)

exp:

目前分数为90分以上的的学生有15人,事务A读取所有分数为90分以上的的学生人数有15人。

此时,事务B插入一条分数为99的学生记录。

这是,事务A再次读取90分以上的的学生,记录为16人。此时产生了幻读。

(大部分数据库缺省的事物隔离级别都会出现这种状况,此种事物隔离级别将带来表级锁)

事务隔离级别描述:

READ UNCOMMITTED:幻读,不可重复读和脏读均允许;

READ COMMITTED:允许幻读和不可重复读,但不允许脏读;

REPEATABLE READ:允许幻读,但不允许不可重复读和脏读;

SERIALIZABLE:幻读,不可重复读和脏读都不允许;

ORACLE默认的是 READ COMMITTED。

MYSQL默认的是 REPEATABLE READ。

如果数据库的隔离级别为REAE_UNCOMMITTED, 则其他线程可以看到未提交的数据, 因此就出现脏读;

如果数据库隔离级别设为READ_COMMITTED,即没提交的数据别人是看不见的,就避免了脏读;但是,正在读取的数据只获得了读取锁,读完之后就解锁,不管当前事务有没有结束,这样就容许其他事务修改本事务正在读取的数据。导致不可重复读。

REPEATABLE READ因为对正在操作的数据加锁,并且只有等到事务结束才放开锁, 则可以避免不可重复读;

REPEATABLE READ只能保证正在被本事务操作的数据不被其他事务修改,却无法保证有其他事务提交新的数据。 则有可能线程1在操作表T1的时候(特别是统计性的事务),其他线程仍然可以提交新数据到表T1,这样会导致线程1两次统计的结果不一致,就像发生幻觉一样。

SERIALIZABLE因为获得范围锁,且事务是一个接着一个串行执行,则保证了不会发生幻读。

由此可见,隔离级别越高,受其他事物干扰越少,并发性能越差。

二个或以上事务在操作同一个共享记录集时,可能会出现的问题:

(A)脏读 (B)不可重复读 (C)幻读

隔离级别:

(1)read-uncommit, (2)read-commit, (3)read-repeatable, (4)read-serializable

都是用来阻止上面的问题的,其中:

(1)什么都阻止不了。

(2)阻止(A)

(3)阻止(A)(B)

(4)阻止(A)(B)(C)

(1)->(4)隔离级别越高,性能损失越大。

修改事务的隔离级别:

在MySQL中默认事务隔离级别是可重复读(Repeatable read).可通过SQL语句查询:

查看InnoDB系统级别的事务隔离级别:

mysql> SELECT @@global.tx_isolation;

结果:

+-----------------------+

| @@global.tx_isolation |

+-----------------------+

| REPEATABLE-READ       |

+-----------------------+

查看InnoDB会话级别的事务隔离级别:

mysql> SELECT @@tx_isolation;

结果:

+-----------------+

| @@tx_isolation  |

+-----------------+

| REPEATABLE-READ |

+-----------------+

修改事务隔离级别:

mysql> set global transaction isolation level read committed;

mysql> set session transaction isolation level read committed;

http://blog.csdn.net/endlu/article/details/51531397

Mysql事务隔离级别与锁

数据库的事务有几种特性,例如一致性和隔离性,一般通过加锁来实现。同时数据库又是一个高并发的应用,如果加锁过度或者不当将严重影响性能。数据库提供了几种隔离级别来供选择,本文通过解析InnoDB的加锁机制是如何实现几种隔离级别,来更深刻的理解mysql的锁。

两阶段锁

首先,事务的所操作分为两个阶段:加锁和解锁,两者不想交。因为事务开始时,并不知道会用到哪些数据,所以加锁阶段随着事务的执行,可能一直在执行。事务结束时,一起将锁释放。注意:不相交!这是两阶段锁的原则,但是有时为了效率也会违反,后面再详述。这种方法由于加锁不是一次获取全部的锁,可能出现死锁,但是事务的并发调度是串行化的。

四种隔离级别:

  • Read Uncommit:未提交读。允许脏读。
  • Read Commit : 提交读。只能读到其他事务已提交的内容。允许不重复读。
  • Repeated Read : 可重复读。同一个事务内的查询与事务开始时是一致的。允许幻读。Mysql默认的级别。
  • Serializable : 串行化的读。每次读都要获取表级锁,读写互相阻塞。

Read Uncommit一般不会使用到,并且没有加锁,所以不讨论。

Serializable也比较简单粗暴,串行化的读写就不会有问题,但是效率低下,称为悲观锁。相对于悲观锁,乐观锁在一定程度上环节了效率的问题。乐观锁大多是基于八本纪录机制实现的,在mysql中为MVCC(多版本并发控制)。我们主要来谈MVCC和RC、RR。

MVCC  (详见http://blog.csdn.net/endlu/article/details/51518377

InnoDB总为每一行后面加入了两个隐藏的列,来实现MVCC。这两个列分别纪录了数据最后一次被哪个事务创建、更新的事务号;该事物是否被删除,被删除的事务的事务号。事务号是递增的。虽然这格外增加的存储空间,每一行都要存储额外的历史版本,而且还要定期删除。但是多版本的实现,为大多数的读惭怍提供了方便:读数据只需要根据事务号来读取某一历史版本,不用再担心并发读写的问题而加锁,效率高,并且可以实现隔离级别中要求的只读取符合条件的值。我们称这种读叫快照读,相反如果读取当前的最新数据叫当前读。mysql在RC/RR下的普通select都为快照读,不用加锁。

在RR级别下,各种操作在MVCC下会有怎么样的效果呢?

  • select时,读取版本号<=当前事务号并且删除版本号为空或>当前事务号的行。
  • insert,保存事务号为当前事务号。
  • delete,保存当前事务号为删除版本号。
  • update,创建新的一行,保存事务号为当前事务号。

快照读/当前读

说完MVCC,我们回到隔离级别。上面说的隔离级别的介绍中,关于RR不能解决幻读的问题,是耳熟能详的,到处都是这么写的。但是实际呢?经过实验,session A select * from test where age = 12; 然后Session B插入一个age=12的行,Session A再次select,并没有返回新插入的行。由此可见Mysql中幻读的读问题已经解决了。原理就是上文提到的快照读。但是,当前读的冲突问题呢?

  • 快照读:

    • select * from test where ... ;
  • 当前读:
    • select * from test where ... in share mode ;
    • select * from test where ... for update ;
    • insert
    • update
    • delete

事务的隔离级别实际上是定义了当前读的级别。为了减少锁竞争,引入了快照读,使得普通的select不同加锁。其他操纵还是需要加锁的。

为了解决当前读的幻读问题,Mysql使用了Next-key锁。就是GAP(间隙锁)和行锁的合并。行锁可以避免并发修改同一行带来的问题,但是插入操作呢?间隙锁GAP就是为了解决这个问题。

在RC级别中,表test,age为主键:

  1. A:select * from test where age = 10;  返回一条记录
  2. A:update test set name = ‘a’ where age = 10;
  3. B:insert into test values(10,‘b’);
  4. B:commit;
  5. A:select * from test where age = 10;  返回两条记录
  6. A:commit ;

在这个例子中,步骤二虽然进行了update,对age=10的记录加了行锁。但是session B插入了新纪录,并提交。A就可以读到。

在RR级别中,重新进行这个实验,A的第二次读,仍然返回一条记录。因为在步骤二中,不止对age=10的行加了行锁,还有间隙锁。session B的插入将被阻塞,等待获取锁,A提交后才能被执行。

InnoDB行锁

上面说到,InnoDB当前读,会对行加锁,防止并发问题。这里有个前提:where条件是索引,可以通过索引来过滤行来对指定行加锁。如果不是索引,InnoDB会对所有行加锁,但是为了提供并发效率。等存储系统返回数据后,会过滤后再对不符合条件的行释放锁。还记得本文开头介绍两阶段锁时,说过有时为了效率会违反这个原则么。就是现在所说的这种情况。先获取全部锁,再释放掉多余的锁。

特殊情况

这里举一个例子:

  1. A:select * from test where age = 10;  返回一条记录
  2. B:insert into test values(10,‘b’);
  3. B:commit;
  4. A:update test set name = ‘qwe’where age = 10;
  5. A:select * from test where age = 10;  返回两条记录

看到这个结果,有人不禁起了疑问:不是说InnoDB在RR级别解决了幻读问题么?怎么同一个事务中两次读读到了不同的行数。

这里A的前后两次读,均为快照读,而且是在同一个事务中。但是B先插入直接提交,此时A再update,update属于当前读,所以可以作用于新插入的行,并且将改行的当前版本号设为A的事务号,所以第二次的快照读,是可以读取到的,因为同事务号。这种情况符合MVCC的规则,如果要称为一种幻读也非不可,算为一个特殊情况来看待吧。

原文地址:https://www.cnblogs.com/cheng2015/p/8487066.html

时间: 2024-08-26 03:00:50

【综合】事务的处理及隔离级别的相关文章

事务的特性与隔离级别

事务的定义: 简单的说事务就是一组原子性的SQL语句.我们可以将这组语句理解为一个工作单元,要 么全都执行,要不都不执行. 事物的四大特性(简称ACID): 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部提交成功,要么全部失败回滚. 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致. 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的.一个事务所做的修改在提交之前

mysql 事务的四种隔离级别

MYSQL标准定义了4种隔离级别,用来限定事务内外的哪些改变是可见的,哪些是不可见的. 低的隔离级一般支持更高的并发处理,并拥有更低的系统开销. 隔离级别由低到高:Read Uncommitted < Read Committed < Repeatable Read < Serializable. 第一:READ UNCOMMITTED (读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交(commit)事务的执行结果. 本隔离级别很少用于实际应用,因为它的性能也不比其他级别好

事务的特征、隔离级别以及事务的传播

事务 一组具有明确边界的,并且是有一定顺序的执行过程.是企业开发过程中必不可少的一门技术.通常用来确保一组执行过程的完整性与一致性. 例如:张三给李四转钱,这就是一个完整的过程,任何一部出问题,事务都是不完整的. 事务的四大特征:原子性(Atomicity):事务是一个完整的过程,不可以再次划分.具有原子的特征. 一致性(Consistency):一旦事务进行,无论有多少个事务,处理事务的过程中,数据总是满足质量守恒定律.入多少---出多少. 隔离性(Isolation):事务与事务执行过程中,

spring事务传播属性与隔离级别

一.Propagation (事务的传播属性) Propagation : key属性确定代理应该给哪个方法增加事务行为.这样的属性最重要的部份是传播行为.有以下选项可供使用: PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择.PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行.PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常.PROPAGATION_R

数据库事务的四种隔离级别

数据库事务的隔离级别有4个,由低到高依次为: Read uncommitted 未授权读取 读未提交 读可允许其他两个事务不能同时进行写操作 事务B读取事务A为提交的数据 避免更新丢失 会出现脏读 Read committed 授权读取 读提交 读可允许其他 未提交的事务禁止其他事务访问进行 事务A读取数据 事务B更改数据 事务A读取B更改后的数据,前后结果不一致 避免脏读 会出现不可重复读(重复读取结果不同) Repeatable read 可重复读取 读不允许写事务进行 写禁止其他事务进行

SQL事务的四种隔离级别和MySQL多版本并发控制

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

事务的特点和隔离级别

Atomic,同一个事务里,要么都提交,要么都回滚 Consistency,即在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏 Isolation,并发事务间的数据是彼此隔离的 Durabiliy,事务提交后,所有结果务必被持久化 原子性,一致性,隔离性,持久性 并发事务带来的问题 dirty read(脏读) unrepeatable read(不可重复读) phantom read(幻读) 事务的隔离级别 Atomic,同一个事务里,要么都提交,要么都回滚 Consistency,

事务的4个隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committed.Repeatable read.Serializable,这四个级别可以逐个解决脏读.不可重复读.幻读这几类问题. 注意:我们讨论隔离级别的场景,主要是在多个事务并发的情况下,因此,接下来的讲解都围绕事务并发. Read uncommitted 读未提交 公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非

理解事务的4种隔离级别

数据库事务的隔离级别有4种,由低到高分别为Read uncommitted .Read committed .Repeatable read .Serializable .而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读.下面通过事例一一阐述它们的概念与联系. Read uncommitted 读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据. 事例:老板要给程序员发工资,程序员的工资是3.6万/月.但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户