使用数据库怎么不会遇到事务呢? 今天我们就一起总结一下吧
只要涉及到金钱转账,强一致性的数据问题 都需要采用事务来去解决

说到事务不得不关注以下几个问题:

事务的特征有哪些?

  1. 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一件商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家手中,消费者的钱也没花出去。
  2. 一致性(Consistency):是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。
  3. 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。
  4. 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

mysql如何保证?

  1. 持久性是通过 redo log (重做日志)来保证的;
  2. 原子性是通过 undo log(回滚日志) 来保证的;
  3. 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
  4. 一致性则是通过持久性+原子性+隔离性来保证;

为什么事务要有隔离性?

为什么事务要有隔离性,我们就要知道并发事务时会引发什么问题!

MySQL 服务端是允许多个客户端连接的,这意味着 MySQL 会出现同时处理多个事务的情况。

那么在同时处理多个事务的时候,就可能出现
脏读(dirty read)
不可重复读(non-repeatable read
幻读(phantom read) 的问题。

脏读

如果一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象。

脏读图例

假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库中读取我的余额数据,然后再执行更新操作,
如果此时事务 A 还没有提交事务,而此时正好事务 B 也从数据库中读取我的余额数据,
那么事务 B 读取到的余额数据是刚才事务 A 更新后的数据,即使没有提交事务。

不可重复读

在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。

不可重复读图例

假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库中读取我的余额数据,
然后继续执行代码逻辑处理,在这过程中如果事务 B 更新了这条数据,并提交了事务,
那么当事务 A 再次读取该数据时,就会发现前后两次读到的数据是不一致的,
这种现象就被称为不可重复读。

幻读

在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象。

幻读图例

假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库查询账户余额大于 100 万的记录,
发现共有 5 条,然后事务 B 也按相同的搜索条件也是查询出了 5 条记录。
接下来,事务 A 插入了一条余额超过 100 万的账号,并提交了事务,此时数据库超过 100 万余额的账号个数就变为 6。
然后事务 B 再次查询账户余额大于 100 万的记录,此时查询到的记录数量有 6 条,发现和前一次读到的记录数量不一样了,
就感觉发生了幻觉一样,这种现象就被称为幻读。

SQL 标准提出了四种隔离级别来规避这些现象,隔离级别越高,性能效率就越低,这四个隔离级别如下:

  1. 读未提交(read uncommitted),指一个事务还没提交时,它做的变更就能被其他事务看到;
  2. 读提交(read committed),指一个事务提交之后,它做的变更才能被其他事务看到;
  3. 可重复读(repeatable read),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;
  4. 串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;

按隔离水平高低排序如下:

隔离水平高低排序

针对不同的隔离级别,并发事务时可能发生的现象也会不同

隔离级别对应问题

  1. 在「读未提交」隔离级别下,可能发生脏读、不可重复读和幻读现象;
  2. 在「读提交」隔离级别下,可能发生不可重复读和幻读现象,但是不可能发生脏读现象;
  3. 在「可重复读」隔离级别下,可能发生幻读现象,但是不可能脏读和不可重复读现象;
  4. 在「串行化」隔离级别下,脏读、不可重复读和幻读现象都不可能会发生。

至此我们了解了相关隔离级别和不同级别带来的问题等相关知识概念,后面我会继续学习更加深入的概念并总结。