MySQL 事务知识整理

2020-12-14  本文已影响0人  章光辉_数据

最近在招 DBA ,在面试的过程中,通过学习也加深了对事务这一概念的理解,下面做个简单的整理。

1、什么是事务

事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。

事务是在引擎层实现的,在 MySQL 中只有使用了 Innodb 引擎的数据库或表才支持事务。MyISAM 引擎就不支持事务。

2、事务的作用

事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。

事务用来管理 insert, update, delete 语句。

3、事务的 ACID 特性

原子性 Atomicity
又叫不可分割性,要么全完成,要么全不完成。就像原子是物质的最小组成单位一样,原子内的各种操作是一个整体。如果执行过程中发生了错误,就会回滚到最初状态。

一致性 Consistency
事务开始前和事务结束后,数据库的完整性不会被破坏,这表明操作的数据必须符合所有规范。

隔离性 Isolation
又叫独立性,数据库允许多个事务同时执行,隔离性可以防止多个事务并发执行导致数据的不一致。

持久性 Durability
事务处理结束后,对数据的修改是永久的,即使系统故障也不会丢失。

4、事务的隔离级别

下面的 4 种隔离级别,越往下,效率越低,并发越低,安全性越高。


1)读未提交(Read Uncommitte,RU)


2)读提交(Read Committed,RC,Oracle 默认的隔离级别)


3)可重复读(Repeatable Read,RR,MySQL 默认的隔离级别)

MySQL Innodb 引擎是如何避免幻读的
MySQL Innodb 引擎做了特殊实现,即加锁。在 RR 级别下,如果查询条件使用了唯一索引,就会对读取到的记录加上行锁;如果查询条件是一个范围查询,那么就会对读取到的记录加上 gap 锁(间隙锁)或者 next-key 锁 ( 行锁 + 间隙锁),避免幻读。
一个事务里,不会读取别的事务提交的变更,而是会读取事务开始时的快照数据。

很多人无法区分幻读与不可重复读,这里简单做个对比。

幻读与不可重复读的区别
不可重复读:在一个事务中多次读取同一个数据时,结果出现不一致。


幻读:在一个事务中使用相同的 SQL 两次读取,第二次读取到了其他事务新插入的行。

4)串行化(Serializable)


总结一下:

隔离级别 是否允许脏读 是否允许非重复读 是否允许幻读
读未提交(RU)
读提交(RC) X
可重复读(RR) X X √(MySQL InnoDB 是 X)
串行化 X X X

隔离的越严实,效率就越低,并发越低,安全性越高。

5、事务的实现原理

事务的隔离性是通过锁实现的,事务的一致性和持久性是通过 Redo Log (重做日志)实现的,事务的原子性是通过 Undo Log (回滚日志)实现的。

5.1、隔离性的实现

事务的实现是基于数据库的存储引擎。不同的存储引擎对事务的支持程度不一样。MySQL 中支持事务的存储引擎有 InnoDB 和 NDB。

InnoDB 是 MySQL 默认的存储引擎,默认的隔离级别是 RR(可重复读),并且在 RR 的隔离级别下更进一步:

  1. 用多版本并发控制(MVCC )解决不可重复读问题:MVCC 允许一个行记录可能有不止一个快照数据,因此使用快照读就可以实现可重复读。
  2. 用行锁 + 间隙锁解决幻读问题:行锁避免了数据的 update/delete,间隙锁避免了数据的 insert 。

因此 InnoDB 的 RR 隔离级别其实也实现了串行化级别的效果,而且保留了比较好的并发性能。

5.2、一致性和持久性的实现

在 InnoDB 的存储引擎中,事务通过 Redo Log 和 InnoDB 存储引擎的日志缓冲( InnoDB Log Buffer ) 实现一致性和持久性。

5.3、原子性的实现

在事务执行的过程中,除了记录 Redo Log,还会记录 Undo Log 。

Undo Log 主要为事务的回滚服务。Undo Log 记录了数据在每个操作前的状态,如果事务执行过程中需要回滚,就可以根据 Undo Log 进行回滚操作。

单个事务的回滚,只会回滚当前事务做的操作,并不会影响到其他的事务做的操作。

6、MySQL 事务控制

MySQL 里的事务控制语句有:

上一篇下一篇

猜你喜欢

热点阅读