目录
4.3. repeatable read(可重复读)(mysql默认的隔离级别为可重复读)
1. 什么是事务?
- 数据库事务是指一组数据库操作,它们被视为一个不可分割的工作单元。
- 事务是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行
- 事务是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事务是最小的控制单元
- 事务适用于多用户同时操作的数据库系统的场景,如银行、保险公司及证券交易系统等等,通过事务的整体性以保证数据的一致性
- 事务是保证了一组操作的平稳性和可预测性的技术
【总结】
事务就是一个整体,是一组数据库操作,是一个不可分割的工作单元,里面的内容要么都执行成功,要么都不成功,不可能存在部分执行成功而部分执行不成功的情况。
【补充】
数据都是通过各种不同技术的存储引擎来引导存储,不同的存储引擎有着各自的特点。在mysql中,常见的存储引擎有innodb、myisam,memory等。其中innodb支持事务(transaction),而myisam,memory等不支持事务。
可以通过show engines;
语句来查看mysql支持的存储引擎
2. 事务的四个特性(ACID)
- 原子性(Atomicity):指事务是一个不可分割的最小工作单位,事务中的操作只有都发生和都不发生两种情况。事务要么全部完成,要么全部取消。 如果事务崩溃,状态回到事务之前(事务回滚)。
- 一致性(Consistency):事务必须使数据库从一个一致状态变换到另外一个一致状态,举一个栗子,李二给王五转账50元,其事务就是让李二账户上减去50元,王五账户上加上50元;一致性是指其他事务看到的情况是要么李二还没有给王五转账的状态,要么王五已经成功接收到李二的50元转账。而对于李二少了50元,王五还没加上50元这个中间状态是不可见的。只有合法的数据(依照关系约束和函数约束)才能写入数据库。
- 隔离性(Isolation):一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。如果2个事务 A和 B 同时运行,事务 A 和B 最终的结果是相同的,不管A和B谁先结束。
- 持久性(Durability):一个事务一旦提交成功,它对数据库中数据的改变将是永久性的,接下来的其他操作或故障不应对其有任何影响。一旦事务提交,不管发生什么(崩溃或者出错),数据要保存在数据库中。
2.1原子性 Atomicity
原子性(Atomicity)指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生
事务是一个完整的操作,事务的各元素是不可分的,即原子的事务中的所有元素必须作为一个整体提交或回滚,如果事务中的任何元素失败,则整个事务将失败。
例如:A 给 B 转帐 100 元钱的时候只执行了扣款语句,就提交了,此时如果突然断电,A账号已经发生了扣款,B账号却没收到加款,这种情况就需要事务的原子性来保证事务要么都执行,要么就都不执行
2.2 一致性 Consistency
一致性(Consistency)指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。事务开始前,数据库中存储的数据处于一致状态;在正在进行的事务中,数据可能处于不一致的状态;但一旦事务成功完成时,数据必须处于一致状态。
例如:对银行转帐事务,不管事务成功还是失败,应该保证事务结束后表中 A 和 B 的存款总额跟事务执行前一致。
2.3 隔离性 Isolation
隔离性(Isolation)指在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间,对数据进行修改的所有并发事务是彼此隔离的,表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务,修改数据的事务可在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据。
2.4 持久性 Durability
持久性(Durability)指不管系统是否发生故障,事务处理的结果都是永久的,一旦事务被提交,事务的效果会被永久地保留在数据库中。在事务完成以后,该事务对数据库所作的更改会持久的保存在数据库之中,并不会被回滚。
3. 事务并发时出现的问题
某个事件不可能总是只有一个事务在运行,可能出现A在操作money_tab表中的数据,B也同样在操作money_tab表,那么就会出现并发问题。对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采用必要的隔离机制,就会发生以下各种并发问题。
3.1 脏读
- 对于两个事务A和B,B读取了已经被A更新但还没有被提交的字段之后,若A回滚即撤销事务,B读取的内容就是临时且无效的
【示意图】
3.2 不可重复读
- 对于两个事务A和B,A读取了一个字段,然后B更新了该字段之后,A在读取同一个字段,值就不同了
【示意图】
3.3 幻读
- 对于两个事务A和B,A在money_tab表中读取了一个字段,然后B又在money_tab表中插入了一些新的数据时,A再读取该表时,就会发现神不知鬼不觉的钱变多了(这种好事多来一点)…
【示意图】
3.4 丢失更新
- 两个事务A和B同时读取同一条记录,A 先修改记录,B 也修改记录(B不知道A修改过),然而当B 提交数据后,B 的修改结果覆盖了 A 的修改结果
【示意图】
4. 事务的四个隔离级别
4.1 read uncommitted(读未提交数据)
【概念】允许事务读取未被其他事务提交的变更。
【问题】脏读、不可重复读和幻读的问题都会出现。
4.2. read committed(读已提交数据)
【概念】只允许事务读取已经被其他事务提交的变更。
【解决】可以避免脏读。
【问题】不可重复读和幻读的问题仍然可能出现。
4.3. repeatable read(可重复读)(mysql默认的隔离级别为可重复读)
【概念】确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新(update)。
【解决】可以避免脏读和不可重复读。
【问题】幻读仍然存在。
4.4. serializable(串行化)
【概念】确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可避免,但性能十分低下(因为你不完成就都不可以弄,效率太低)。
【解决】所有并发问题都可避免。
【遗憾】性能十分低下(因为你不完成就都不可以弄,效率太低)