**
(详细)事务特性和隔离级别
事务特性和隔离级别
一.数据库事务特性
数据库事务transaction是组合一系列数据库操作(增删查改)作为一个逻辑处理单元的操作。单元内存ACID四大特性。
原子性(Atomicity):一个事务内所有操作,要么全部成功,要么全部失败。
一致性(Consistency):事务执行完毕后,数据库结果与业务规则一致。如转账业务,无论成功与失败,前后金额总和不变。
隔离性(Isolation):并发的数据库事务操作场景下,各事务间相互隔离,互不影响。
持久性(Durability):事务一旦提交后,事务执行结果永久保留在数据库中。
二.事务隔离级别
2.1 READ_UNCOMMITTED
读未提交:一个事务a可以在其他事务b未提交前,读取b操作的数据。这个隔离级别容易造成脏读。
例子:
将事务设置为READ_UNCOMMITTED
Mysql中建 acct_balance表(账号,余额)
事务a中开始事务,将账号111余额扣除50元,但事务未提交,另外见一个mysql客户端,
开启事务b进行余额查询,查询到111账号余额是50元。
事务a rollback撤回,余额回归100元,事务b读到的数据并不是最终的真实数据,即为脏数据。
2.2 READ_COMMITTED
读已提交,事务a只能等事务b提交后,才能读取到最新提交后的数据,能解决脏读问题。
从图中操作可以看到,事务b虽然已经改了余额,但尚未提交,事务a读取到提交前的数据,这就解决了脏读的问题,事务b提交后,事务a再次查询,得到提交后的数据。可以看出,前后两次事务a查询得到的数据说不一致的,造成了不可重复读的问题。
2.3 REPEATABLE_ABLE(MySQL默认隔离级别)
可重复读,顾名思义,事务a开始对一数据操作后,到提交前这一段时间内,就算事务b对同一数据进行修改并提交,数据a所读取的某条数据的值都是一致的。也就是说事务a开始到提交这段期间所读取的数据,不收外界影响,形成可重复读。
可重复读没能解决幻读的问题。即事务a在一个事务内多次查询,有可能查询到不同条数据记录。原因为若事务a开启事务到事务提交这段期间内,若事务b有插入删除操作,并提交,事务a是可以查询到数量上的变动的。这就造成事务a在一个事务内查询数目的结果不一致。造成幻读。
不可重复读对应的是对一个数据的update操作(事务b update提交前后,事务a查询数据值不一致),而幻读则对应的所对一张表数据的insert操作(事务b insert 提交前后,另一事务a查询个数的不一致)
但mysql采用多版本并发控制(MVCC)解决问题,在mysql中可重复读不会出现幻读现象。
故下图步骤3中数据个数不变。而后在步骤4中将账号111余额增加50时,更新后的余额为150,所在事务b提交结果的基础上增加的。原因所mysql中使用的mvcc控制,select 只是进行快照读(读取历史版本),不回更新为最新版本再去读取。而update,insert,delete等修改操作是会读取数据最新版本的。保证数据的一致性。
2.4SERIALIZABLE
顺序读(串行读),解决一切脏读,不可重复度,幻读问题。但事务只能串行执行。
串行读时,事务b若想进行更新操作,则必须等事务a提交才能进行更新操作,但事务b的读操作比等到事务a提交才能读。也就是说,a,b开启事务后,select * from acct_balance/
select * from acct_balance where account=111会锁住整张表,该锁属于可重入的读锁,对于读读共享,读写,写写排斥。
总结:
四种隔离事务产生问题比较:
事务隔离级别 脏读 不可重复度 幻读
READ_UNCOMMITTED
READ_COMMITTED ×
REPEATABLE_ABLE × × (mysql中不产生)
SERIALIZABLE × × ×
MySql中默认的事务隔离级别为可重复读 REPEATABLE_ABLE。Oracle、Sql Server等大部分数据库,默认的事务隔离级别所读提交READ_COMMITTED。