十七、事务
事务
事务的ACID特性
Atomic(原子性)
所有语句作为一个单元全部成功执行或全部取消。不能出现中间状态。
Consistent(一致性)
如果数据库在事务开始时处于一致状态,则在执行该事务期间将保留一致状态。
Isolated(隔离性)
事务之间不相互影响。
Durable(持久性)
事务成功完成后,所做的所有更改都会准确地记录在数据库中。所做的更改不会丢失。
事务的生命周期(标准的事务控制语句)
如何开启事务
begin ;
标准的事务语句
一条DML语句就是一个事务
insert
update
delete
案例
#使用回滚修改不生效
mysql> use world;
mysql> begin;
mysql> update city set countrycode='CHN' where id=1;
mysql> update city set countrycode='CHN' where id=2;
mysql> update city set countrycode='CHN' where id=3;
mysql> rollback;
事务的结束
提交:
commit;
回滚:
rollback;
自动提交机制(autocommit)
只要执行DML语句,则自动提交事务,不需要手动commit;
#默认开启自动提交
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.01 sec)
#在当前会话关闭自动提交
mysql> set autocommit=0;
#全局级别关闭自动提交,需要断开重连生效
mysql> set global autocommit=0;
#修改配置文件,重启数据库,永久生效
$ vim /etc/my.cnf
[mysqld]
autocommit=0
隐式提交机制
begin;为写提交再写begin,之前begin的语句会自动提交
mysql> begin;
mysql> update city set countrycode='CHN' where id=1;
mysql> update city set countrycode='CHN' where id=2;
mysql> begin;
导致自动提交的非事务语句
DDL语句
ALTER、CREATE、DROP
DCL语句
GRANT、REVOKE、SET PASSWORD
锁定语句
LOCK TABLES 和 UNLOCK TABLES
导致隐式提交的语句示例:
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE
保证事务的ACID的相关概念
redo log
重做日志文件ib_logfile0~1
位于mysql默认/data/目录下
默认50M,轮询使用
redo log buffer
负责redo重做日志的读写内存区域
保存着数据页的变化信息+数据页的LSN号
ibd
存储数据行和索引文件
data buffer pool
数据缓冲区池,负责ibd数据和索引读写的内存缓冲区域
LSN
日志序列号
ibd ,redolog ,data buffer pool, redo buffer文件都有LSN号
MySQL每次启动数据库,都会比较ibd和redolog的LSN,必须要求两者LSN一致数据库才能正常启动
WAL
全称叫write ahead log
日志优先写入硬盘的方式实现持久化,持久化即把内存的数据写入到硬盘
日志是优先于数据写入磁盘的
脏页
例如内存脏页,内存中发生了修改,没写入到磁盘之前,我们把内存页称之为脏页
通过对比LSN号来实现
CKPT
全称叫Checkpoint
检查点,就是将脏页刷写到磁盘的动作
TXID
事务id号,InnoDB会为每一个事务生成一个事务号,伴随着整个事务
在事务开始时,begin;命令执行后就会产生一个事务ID号
redo
也叫重做日志或前滚日志,主要保证持久性,也就是ACID中的D
1、记录了内存数据页的变化
2、提供快速的事务提交
3、提供CSR前滚功能
案例
1、开启事务,如将A列的值从1改为2,该数据假设在100号数据页上,一个数据页为16KB,mysql会将100号数据页加载到内存data buffer pool中。假如此时的数据页的LSN为101
2、updata语句执行,A从1变为2,该数据页LSN从101变为102,此时redo buffer内存中记录了data buffer pool内存中数据页的变化,此条日志大小为几个字节,并记录更改后的LSN号为102(先将redo写入磁盘是因为数据小,写入快)
3、comint;提交事务会将redo buffer中的日志信息(日志信息记录着A从1变为2的变化)写入硬盘,此时的LSN号为102
4、此时突然断电。内存数据消失。重启数据库后MySQL会检查所有数据页的LSN是否跟redo log中记录的LSN一致。
5、此时会将redo log加载到内存redo buffer中,重做整个过程,然后出发CKPT校验点,然后将重做的data buffer pool数据写入硬盘,从而使ibd数据页中的LSN变为102跟redo log日志中的LSN一致,从而mysql正常启动完成。
以上过程称为CSR前滚操作。
redo的刷写策略
commit;命令执行时会将当前事务的redo buffer写入到磁盘
还会顺便将一部分redo buffer中没有提交的事务日志也写入到磁盘
MySQL在启动时,必须保证redo日志文件和数据文件LSN必须一致, 如果不一致就会触发CSR,发生如上第5点,最终使LSN保证一致,MySQL才会启动成功。
当事务没有执行commit就断电时就要用到undo
undo
undo也叫回滚日志
主要保证原子性,也就是ACID中的A,要么全部成功,要么执行不成功。
主要功能
- 记录了数据修改之前的状态,如果遇到断电,方便回滚到之前的状态。
- rollback 将内存的数据修改恢复到修改之前
- 在CSR中实现未提交数据的回滚操作
- 实现一致性快照,配合隔离级别保证MVCC(多版本并发控制),读和写的操作不会互相阻塞。
参考资料: 什么是隔离级别
详见: 09.day06 事务AACID特性-redo+undo配合工作完成CSR过程 从10min开始到最后
学习来自:郭老师博客,老男孩深标DBA课程 第五章