MySQL数据库事务
一、数据库事务基本概述
1.什么是事务
简单来说,事务就是一组逻辑的操作单元,多个操作(增删改查)在一起完成的事情就是事务。对事务来说,所有的事务来说,事务要么提交(commit),数据进行永久的保存下来,要么就事务,回滚(rollback)到事务前的状态。
2.MySQL存储引擎支持事务情况
在MySQL数据库中,可以使用show engines的指令来查看Mysql 都支持那些存储引擎以及是否支持事务。
使用指令查询后,在MySQL存储引擎中,只有InnoDB是支持事务的。
3.事务的ACID特性
- 原子性(A):原子性指的是一个事务是不可再分的最小单位,事务在执行过程中,事务中的操作要么全部执行成功,要么全部执行失败。如:一个事务中,有update语句1和update语句2,当update语句1执行成功,但update语句2执行失败,此时整个事务都是失败的,语句1和2都需要失败回滚。
- 一致性(C):一致性指的是事务在执行前,和执行成功后,数据的是一致的不变的,这个不变,指的是数据从一个合法的状态,转变成另外一个合法的状态,这个合法状态是一个自己约束的条件。比如:用户A(500元)向用户B(0元)成功转账100元,此时用户A的余额为400元,用户B的余额100,总金额始终是不变的(500元),总金额不变就体现出了事务的一致性。
- 隔离性(I):隔离性指的是一个事务在执行操作数据的过程中,不受其他事务的影响。也就是说,在并发情况下, 一个事务在操作的共享数据,其他事务不能对这个数据进行操作。只能这个事务提交或者回滚结束后,其他事务才能对这个数据进行操作。隔离性后面会说,有很多的解决方案。
- 持久性(D):持久性很好理解,就是一个事务进行数据的写操作,一旦事务提交成功后,那么被操作的数据就是永久的,不管数据库的故障都不会影响该数据。
4.事务的状态
- 活动的:指事务正在执行,还commit未提交。
- 部分提交:指事务已经commit提交成功,但事务操作的数据还保存在buffer pool缓冲区中,还没有刷盘到磁盘。
- 失败的:指事务在执行的过程中,发生其他错误或者手动中止事务导致失败,又或者部分提交成功的事务,在刷盘到磁盘是发生错误。事务还未回滚时的状态。
- 已提交:指【部分提交】状态下的数据,成功刷盘到磁盘持久化后的状态。
- 中止的:指【已中止】的状态下,数据回滚成功后的状态。
5.事务的开启和关闭
- 开启:使用begin或者start transaction这两个关键字,可以开启一个事务。
- 关闭:事务提交(commit)或回滚(rollback)后,事务会关闭掉。
6.事务并发下出现的问题
-
脏写:脏写指一个事务修改了另外一个事务修改后还未提交的数据。比如:两个事务A和B,当A事务进行id为1的数据进行修改操作,还没提交事务,事务B也对id为1的数据进行修改,然后事务A提交后,事务B进行回滚操作。导致事务A修改的数据也同步被回滚到最初状态,导致最后事务A的数据没有修改到。事务B修改了事务A未提交的数据,这种情况就叫脏写。
-
脏读:脏读指一个事务查询到了另一个事务修改未提交的数据。比如:事务A和B,事务A开启事务后,事务B也开启,事务B对id为1的数据(name=李四)进行修改后未提交,此时事务A去查询id为1的数据(得到name=李四),此后事务A提交了,事务B将事务回滚了,id为1的name还是张三,导致事务A查询得到的数据是不存在的。
-
不可重复读:指同一个事务,多次读取同一条数据,期间有其他事务更新了该条数据的内容并提交,导致前后读取到的数据不一致,就是不可重复读。比如:事务A开启事务,查询数据库id为1的数据,查询到name=张三,后面事务B(隐式事务,单独为事务,更新后自动提交)更新是id为1的name=李四,事务A再去查询,查询到name=张三,事务B(隐式事务,单独为事务,更新后自动提交)更新是id为1的name=王五,事务A再去查询,查询到name=王五。同一次事务,三次读取的数据都不一样,出现了不可重复读的问题。
-
幻读:指一个事务A在查询字段区间范围的内容时,期间其他事务在该范围插入了几条数据,导致事务A再次查询相同字段相同范围条件的数据时,出现多出了好几个数据。相当于出现了幻觉。
7. MySQL的四种隔离级别
- 隔离级别是SQL做的规定,主要是用来避免上面所说的4种并发情况下出现的并发隔离问题,在不同的数据库种,都有不通过的默认隔离级别。
- 默认隔离级别:MySQL默认的隔离级别是不可重复读,MySQL在该隔离级别下,一定程度会避免幻读的,后面讲锁和MVCC的时候细说。
- 四种隔离级别:
- 读未提交(read uncommitted):该隔离级别下,所有事务都可以读取到其他事务未提交的数据,解决了脏写,没有解决脏读、不可重复读、幻读。
- 读已经提(read committed):该隔离级别下,所有事务都不能读取到其他事务未提交的数据。解决了脏读的问题,但是没有解决不可重复读、幻读。
- 可重复读(repeatable read):该隔离级别下,一条事务A读取到数据后,后面其他事务再更新并提交该数据,事务A读到的数据还是原来的。该隔离级别解决脏读、不可重复读的问题,但是幻读没有解决。
- 可串行化(serializable):在该隔离级别下,对每一次读都进行加锁,能解决幻读情况的发生,但是会使数据库性能非常差,因为事务在读取数据时,其他事务对表的增删改都是禁止状态。