Skip to content

Latest commit

 

History

History
85 lines (52 loc) · 3.84 KB

事务.md

File metadata and controls

85 lines (52 loc) · 3.84 KB
date created date modified
2022-01-25, 19:06:48
2022-08-10, 16:09:46

Meta

  • alias: Transaction
  • parent :: [[MOC MySQL]]
  • siblings ::
  • child :: [[InnoDB 如何实现事务 4 特性]]
  • refs:

事务 Transaction

Transaction 交易,一手交钱一手交货,不能只发生一个。

事务:保证单一逻辑单元的一组操作集合,要么全部成功,要么全部失败。

保证了数据库中数据的一致性,如果在中间某环节出了错就会回滚到事务没有执行的状态。

事务特性

实现事务必须要实现的 4 个特性。InnoDB 如何实现事务 4 特性

Atomicity 原子性

  • 一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。

Isolation 隔离性

  • 多个并发事务同时对共享数据进行读写时,防止多个事务并发执行时由于交叉执行而导致数据不一致
  • 理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。但是这样子的话对性能影响太大

Consistency 一致性

  • 事务操作前和操作后,数据满足完整性约束、数据库保持一致性状态。

Durability 持久型

  • 事务提交后,即使发生系统崩溃,对数据库的修改是永久的

隔离性与隔离级别

MySQL 允许多个客户端连接,故可能会出现事务并发(并行)情况。

保证事务的绝对隔离性会导致性能很差,故需舍弃部分隔离性要求以提供性能。

事务的隔离级别即实现隔离性的程度。

并发问题:

  • 脏写
    • 一个事务(已提交)修改了另一个未提交事务修改过的数据
  • 脏读
    • 一个事务读到了另一个未提交事务修改了的数据
  • 不可重复读
    • 事务 A 读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,事务 A 都能查询得到最新值(每次读值都不一样)
  • 幻读
    • 一个未提交事务 A 按照某个相同条件多次查询记录,期间另一个事务又向表中插入满足查询条件的记录,事务 A 再次按该条件查询时读取到了新插入的记录(后面查询到的记录数比前一次查询多)

问题严重程度:脏写 > 脏读 > 不可重复读 > 幻读。

隔离级别 SQL 标准:

脏写 >(读未提交) 脏读 >(读已提交) 不可重复读 >(可重复读) 幻读 >(串行化)。

CleanShot2022-06-24at18.13.11

  • 读未提交:可以读到未提交事务修改过的记录,故可能发生脏读
  • 读已提交:只能读到已提交事务修改过的记录,故不可能发生脏读,但可能发生不可重复读
  • 可重复读:见名知意,解决了不可重复读问题。多次 SELECT 查询得到的结果是一样的。
  • 串行化:事务只能串行执行,任何并发问题都不可能发生

MySQL 在 REPEATABLE READ 隔离级别下,可以禁止幻读问题的发生。

使用 READ COMMITTED 隔离级别的事务在每次查询开始时都会生成一个独立的 ReadView

对于使用 REPEATABLE READ 隔离级别的事务来说,只会在第一次执行查询语句时生成一个 ReadView,之后的查询就不会重复生成了。

InnoDB 使用锁来保证不会有脏写情况的发生,也就是在第一个事务更新了某条记录后,就会给这条记录加锁,另一个事务再次更新时就需要等待第一个事务提交了,把锁释放之后才可以继续更新。

使用锁保证串行化