学不会的数据库事务
事务
事务(Transaction,简写为 tx),由一步或几步数据库操作(DML 语句)序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行(一组原子性的 SQL 査询)
事务的 4 个特性(ACID 性)
原子性(Atomicity):
- 事务是数据库的逻辑工作单位,事务中包含的所有操作要么全部提交成功,要么全部失败回滚
一致性(Consistency): - 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态
隔离性(Isolation): - 一个事务所做的修改在最终提交以前,对其它事务是不可见的
持久性(Durability): - 也称永久性,一个事务一旦提交,则其所做的修改就会永久保存到数据库中,接下来的其它操作或故障不会对其执行结果有任何影响
事务的 ACID 是通过 InnoDB 日志和锁来保证:事务的隔离性是通过数据库锁的机制实现的,原子性和持久性通过 redo log(重做日志)来实现,一致性通过 undo log 来实现
在修改表的数据时,先需要修改其内存拷贝,再把该修改行为记录到重做日志 Buffer(redo log buffer)中,在事务结束后将重做日志写入磁盘,并通知文件系统刷新缓存中的数据到磁盘文件
事务控制的命令
begin 或 start transaction、commit、rollback
事务自动提交
- MySQL 默认采用自动提交(autocommit = 1)模式,即如果不是显式地开始一个事务,则毎个查询都被当作一个事务执行提交操作
- 在执行 DDL、DCL 操作之前会强制执行 commit 提交当前的活动事务
事务并发问题
脏读
- 一个事务读到另一个事务未提交的更新数据
不可重复读
- 一个事务两次读同一行数据,期间有另一个事务提交了更新,导致这两次读到的数据不一样
幻读
- 一个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当再次读取该范围的记录时,会产生幻行
第一类丢失更新(回滚丢失)
- 撤消一个事务时,把其它事务已提交的更新的数据回滚掉了
第二类丢失更新(覆盖丢失)
- 提交一个事务时,把其它事务已提交的更新的数据覆盖了
事务隔离级别
-
应用程序设计者可以允许并发的事务运行在不同的隔离级别上,从而牺牲一些正确性来换取更大的吞吐量。
-
低的隔离级别提高了事务的并发程度,但是增加了数据库中含有不正确数据的风险。
-
有一些事务运行在最高的隔离级别,但是有另外一些事务却运行在较低的,可以访问未提交状态的隔离级别。
-
运行在较低隔离级别的事务可能产生无效的数据。应用程序设计者必须阻止之后运行在较高隔离级别的事务去访问这些无效的数据,继而传播错误。
读未提交
- 事务中的修改,即使没有提交,对其它事务也都是可见的
读已提交
- 一个事务开始时,只能“看见”其它已经提交的事务所做的修改
可重复读
- 同一个事务中多次读取同样记录的结果是一致的,当 A 事务修改了一条记录但未提交时,B 事务将不允许修改这条记录(会被阻塞,innodb_lock_wait_timeout,默认是 50s)
可串行化
- 事务顺序执行,事务在读取的毎一行数据上都加锁
InnoDB 默认的事务隔离级别是 Repeatable Read(可重复读),并且通过间隙锁(next-key locking)策略防止幻读的出现
记忆图