事务的基本特性和隔离级别
事务基本特性 ACID 分别是:
- 原子性:指一个事务中的操作要么全部成功,要么全部失败。
- 一致性:指数据库总是从一个一致性的状态转换到另外一个一致性的状态。
- 隔离性:指一个事务的修改在最终提交前,对其他事务是不可见的。
- 持久性:指一旦一个事务提交,所做的修改就会永久保存在数据库中。
事务的隔离级别有 4 种,分别是:
- 读未提交:可能会读到其他事物未提交的数据,叫做脏读。
- 读已提交:可能会造成两次读取结果不一致,叫做不可重复读。
- 可重复读:是 mysql 的默认级别,就是每次读取结果都一样,但是可能产生幻读。
- serializable 串行化:一般是不会使用的,他会给每一行读取的数据加锁,会导致大量超时和锁竞争问题。
不可重复读和幻读的区别
不可重复读重点在于 update 和 delete,幻读的重点在于 insert。
在可重复读中,该 sql 第一次读取到数据后,就将这些数据加锁,其他事务就无法修改这些数据了,就可以实现可重复读了。但是这种方法却无法锁住 insert 的数据,
所以当事务 A 先读取了数据,或者修改了全部数据,事务 B 还是可以 insert 数据提交,这时事务 A 就会发现莫名其妙多了一条之前没有的数据,这就是幻读。不能通过行锁来避免。
需要 Serializable 隔离级别,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大地降低数据库的并发能力。
那 ACID 靠什么保证的呢?
- A 原子性 由 undo log 日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的 sql
- C 一致性一般由代码层面来保证
- I 隔离性由 MVCC 来保证
- D 持久性,由内存 + redo log 来保证,mysql 修改数据同时在内存和 redo log 记录这次操作,事务提交的时候通过 redo log 刷盘,宕机的时候可以从 redo log 恢复。