date created | date modified |
---|---|
2022-01-25, 19:06:48 |
2022-08-10, 16:09:46 |
- alias: Transaction
- parent :: [[MOC MySQL]]
- siblings ::
- child :: [[InnoDB 如何实现事务 4 特性]]
- refs:
Transaction 交易,一手交钱一手交货,不能只发生一个。
事务:保证单一逻辑单元的一组操作集合,要么全部成功,要么全部失败。
保证了数据库中数据的一致性,如果在中间某环节出了错就会回滚到事务没有执行的状态。
实现事务必须要实现的 4 个特性。InnoDB 如何实现事务 4 特性
- 一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
- 多个并发事务同时对共享数据进行读写时,防止多个事务并发执行时由于交叉执行而导致数据不一致
- 理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。但是这样子的话对性能影响太大
- 事务操作前和操作后,数据满足完整性约束、数据库保持一致性状态。
- 事务提交后,即使发生系统崩溃,对数据库的修改是永久的
MySQL 允许多个客户端连接,故可能会出现事务并发(并行)情况。
保证事务的绝对隔离性会导致性能很差,故需舍弃部分隔离性要求以提供性能。
事务的隔离级别即实现隔离性的程度。
并发问题:
- 脏写
- 一个事务(已提交)修改了另一个未提交事务修改过的数据
- 脏读
- 一个事务读到了另一个未提交事务修改了的数据
- 不可重复读
- 事务 A 读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,事务 A 都能查询得到最新值(每次读值都不一样)
- 幻读
- 一个未提交事务 A 按照某个相同条件多次查询记录,期间另一个事务又向表中插入满足查询条件的记录,事务 A 再次按该条件查询时读取到了新插入的记录(后面查询到的记录数比前一次查询多)
问题严重程度:脏写 > 脏读 > 不可重复读 > 幻读。
隔离级别 SQL 标准:
脏写 >(读未提交) 脏读 >(读已提交) 不可重复读 >(可重复读) 幻读 >(串行化)。
- 读未提交:可以读到未提交事务修改过的记录,故可能发生脏读
- 读已提交:只能读到已提交事务修改过的记录,故不可能发生脏读,但可能发生不可重复读
- 可重复读:见名知意,解决了不可重复读问题。多次 SELECT 查询得到的结果是一样的。
- 串行化:事务只能串行执行,任何并发问题都不可能发生
MySQL 在 REPEATABLE READ
隔离级别下,可以禁止幻读问题的发生。
使用 READ COMMITTED
隔离级别的事务在每次查询开始时都会生成一个独立的 ReadView
。
对于使用 REPEATABLE READ
隔离级别的事务来说,只会在第一次执行查询语句时生成一个 ReadView
,之后的查询就不会重复生成了。
InnoDB 使用锁来保证不会有脏写情况的发生,也就是在第一个事务更新了某条记录后,就会给这条记录加锁,另一个事务再次更新时就需要等待第一个事务提交了,把锁释放之后才可以继续更新。
使用锁保证串行化