*博客搬家:初版发布于 2017/04/10 00:37 原博客地址:https://my.oschina.net/sunqinwen/blog/875833
数据库事务的隔离级别
讲事务的隔离级别之前,先来介绍一下数据库事务的几个特性:
(1)原子性
最基本的特性,意思是在一个事务内里所有关于数据库的操作,要么全部成功,要么全部失败;成功时意味着本次操作所有数据库相关的写操作全部持久化,无法更改,失败意味着本次操作相对于操作前对数据库没有任何影响和改变。
(2)一致性
指的是一次完整的事务必须将数据库的一个一致状态转变到另外一个一致状态。
一致性写:
例如:事务A要做的操作是将A、B、C三个记录修改为D、E、F,那么A、B、C----->D、E、F的过程就满足了事务一致性,但是如果出现类似:A、B、C---->D、E、C(A、B修改成功,但是C未修改)则认定违背了事务的一致性,简单理解一致性就是指事务的“初始状态”到“修改完成状态”与“目标状态一致”。
一致性读:
事务A在某一刻发起查询请求,那么查询结果是以那一刻为准,保证了数据在查询一刻的一致性。
(3)持久性
指一次事务的成功提交对数据库造成的修改是永久性的。
(4)隔离性
当多个用户并发访问数据库时,数据库为每一个用户开启的事务不可以被其他事务所影响,也就是说并发事务间要相互独立不受到干扰。关于隔离性分了集中隔离等级,本篇文章将详细介绍这几种隔离等级。
下面来讲下事务隔离级别:
(1)Read Uncommitted(读未提交)
这个隔离级别下未被提交的事务下所做的任何操作都可以被其他事务所读取到,这时候会造成数据的脏读、幻读、不可重复读问题。
(2)Read Committed(读已提交)
这个隔离级别下未被提交的操作不可以被其他事务所读取到,简单来讲就是单个事务里的内容在事务成功提交之前,是不会被其他事务所读取(发现)到的,但是这样同样会出现幻读、不可重复读现象。
举个栗子:事务T1要对C表做添加操作,同时事务T2里要读取C表,T2第一次读取C表时返回1条数据,这时T1执行完毕,那么T2如果再次取一次C表数据就会发现多出一条数据。
(3)Repeatable Read(可重读)
Mysql默认的隔离级别,这个隔离级别下同一事务读取到的数据一致(简单点说就是T1一旦开始,读取到数据如果中间被T2修改,那么T1再次读取该数据是和第一次读取时一样的),因此,在该隔离级别下,不会造成脏读、不可重复读,但依旧会造成幻读现象。
(4)Serializable(串行化)
最高隔离级别,会为每个事务排序(为每条数据都加上锁),使之执行串行化,不可能产生冲突,因此解决了脏读、幻读、不可重复读问题,但是会造成锁竞争甚至超时,一般不会采用这种极端的隔离机制。
事务并发过程中产生的问题介绍:
(1)脏读
一个事务读取到了另外一个事务中未提交的数据。
(2)不可重复读
一个事务读取到了另外一个事务中提交的修改掉的数据。
(3)幻读
一个事务读取到了另外一个事务中添加的数据。
Tip:不可重复读和幻读的区别在于着重点一个是update,一个是insert
总结四种隔离级别所造成和避免的问题,请先看以上内容后再看此表:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
Read Uncommitted | 是 | 是 | 是 |
Read Committed | 否 | 是 | 是 |
Repeatable Read | 否 | 否 | 是 |
Serializable | 否 | 否 | 否 |