一、简介
1. 什么是事务
事务是由一个或多个sql语句组成一个最小的不可再分的工作单元。里面的内容要么都执行成功,要么都不成功。
2. 事务的ACID特性
原子性(atomicity)
事务是一个不可分割的工作单元,要么全部提交,要么全部失败回滚。一致性(consistency)
一致性指事务执行前后,数据从一个合法性状态变换到另一个合法性状态。例如要满足存在的约束,满足数据的一致性等、隔离性(isolation)
指一个事务的执行不能被其他事务干扰。持久性(durability)
一个事务一旦提交成功,它对数据库中数据的改变将是永久性的,接下来的其他操作或故障不应对其有任何影响。
3. 存储引擎支持情况
show engines
命令可以查看mysql存储引擎支持事务的情况。
在mysql中,只有innodb是支持事务的。
二、开启事务
1. 显式事务
START TRANSACTION或BEGIN能显式的开启一个事务。
BEGIN;
# 或者
START TRANSACTION;
START TRANSACTION相较于BEGIN可以在后边跟随几个修饰符。
READ ONLY
: 表示当前事务是一个只读事务READ WRITE
: 当前事务是一个读写事务WITH CONSISTENT SNAPSHOT
启动一致性读(在开启事务的时候就生成Readview)
事务的相关操作如下:
COMMIT;
ROLLBACK;
ROLLBACK TO [SAVEPOINT];
SAVEPOINT 保存点名称;
RELEASE SAVEPOINT 保存点名称; #删除保存点
2. 隐式事务
如果不显式使用START TRANSACTION或BEGIN开启一个事务,那么每一条语句是一个独立的事务,这种特性叫做事务的自动提交。
如果想关闭自动提交,有两种方法:
- 显式使用START TRANSACTION或BEGIN
- 把系统变量
autocommit
的值设置为off
注意事项——隐式提交
- 数据定义语言。当使用create、alter、drop等语句去修改数据库对象时,就会隐式提交前边语句所属的事务。
- 当我们在一个事务还未提交或回滚时又使用START TRANSACTION或BEGIN开启一个事务时,会提交上一个事务。
三、事务的隔离级别
1. 介绍
SQL在并发事务执行过程中可能存在以下问题:
脏写、脏读、不可重复读、幻读
mysql提供四种隔离级别,用来解决并发问题:
READ UNCOMMITTED
: 读未提交,在该隔离级别下,所有事务都可以看到其他事务未提交的数据。不能避免脏读、不可重复读、幻读。READ COMMITTED
: 读已提交,一个事务只能看到已经提交的事务。可以避免脏读,不能避免不可重复读、幻读。REPEATABLE READ
: 可重复读,事务A在读到记录后,其他事务对该记录修改后,A事务读到的还是原来的内容。可以避免脏读、不可重复读,不能避免幻读。这是mysql默认的隔离级别。SERIALIZABLE
: 可串行化,所有事务串行执行。
2. 设置
show variables like 'tx_isolation'; # 查看隔离级别,mysql5.7.20之前
show variables like 'transaction_isolation' # 查看隔离级别,mysql5.7.20之后
select @@transaction_isolation
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别'
四、undo日志
undo log是事务原子性的保证,在事务更新数据时需要先写入undo log。
1 作用
回滚数据
用户对undo日志可能有误解:undo用于将数据库物理地恢复到执行语句或事务之前的样子。但事实并非如此。undo是逻辑日志,因此只是将数据库逻辑地恢复到原来的样子。所有修改都被逻辑地取消了,但是数据结构和页本身在回滚之后可能大不相同。
这是因为在多用户并发系统中,可能会有数十、数百甚至数千个并发事务。数据库的主要任务就是协调对数据记录的并发访问。比如,一个事务在修改当前一个页中某几条记录,同时还有别的事务在对同一个页中另几条记录进行修改。因此,不能将一个页回滚到事务开始的样子,因为这样会影响其他事务正在进行的工作。
MVCC
undo的另一个作用是MVCC,即在InnoDB存储引擎中MNCc的实现是通过undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。
2 结构
InnoDB对undo log的管理采用段的方式,也就是回滚段(rollback segment)
,每个回滚段记录类1024个undo log segment
。
innodb_undo_directory : 设置文件所在路径。
innodb_undo_tablespaces : 设置文件数量.
undo log类型分为:
- insert undo log
因为insert操作的记录,只对事务本身可见,对其他事务不可见。故该undo log可以在事务提交后直接删除,不需要进行purge操作
- update undo log
该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除
3 工作流程
五、redo日志
redo log称为重做日志,提供再写入操作,恢复提交事务修改页操作,用来保证事务的持久性。
redo log记录的是物理级别上页的修改操作。
1. WAL
InnoDB的事务存储引擎,其通过Force Log at Commit机制实现事务的持久性,即当事务提交时,先将redo log buffer写入到redo log file进行持久化,待事务的commit操作完成后才算完成。这种做法也被称为Write-Ahead Log(预先日志持久化),在持久化一个数据页之前,先将内存中相应的日志持久化。
2. 刷盘策略
通过调整innodb_flush_log_at_trx_commit
,支持不同的刷盘策略:
0
: 表示每次事务提交时不进行刷盘操作,由系统后台线程每隔1s进行一次同步。1
: 默认为1,表示每次事务提交时都将进行同步,刷盘操作2
: 表示每次事务提交时都只写到oage cache,不进行同步,由os自己决定什么时候同步到磁盘。