事务特性
- 原子性(atomicity)
- 一致性(consistency)
- 隔离性(isolation)
- 持久性(durability)
事务隔离级别
READE UNCOMMITTED(未提交度)
允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
READ COMMITTED(提交读)
只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
REPEATABLE READE(可重复读)
可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
SERIALIZABLE(可串行化)
完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | 可能 | 可能 | 可能 |
已提交读 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
可串行化 | 不可能 | 不可能 | 不可能 |
事务隔离级别名词解释
什么是脏读
脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
什么是不可重复读
指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
什么是幻读
指的是当某个事务在读取某个范围内的记录时, 另外一个事务又在该范围内插入了新的记录,当之前的事务再次 读取该范围的记录时,会产生幻行(Phantom Row)。
MySQL利用间隙锁解决了幻读
更改Mysql事务隔离级别
临时生效
SET @@session.transaction_isolation = 'READ-UNCOMMITTED';
SET session transaction isolation level read uncommitted;
永久性生效
打开Mysql配置文件增加如下:
transaction-isolation = READ-COMMITTED
查看Mysql事务隔离级别
# 全局配置
SELECT @@global.tx_isolation;
# 当前会话配置
select @@session.tx_isolation;
redo log 和 undo log
提到MySQL事务不得不说下,重做日志和回滚日志。
重做日志
基本概念
重做日志用来实现事务的持久性,即事务 ACID 中的 D。其由两部分组成:
- 内存中的重做日志缓冲(redo log buffer)
- 磁盘重做日志文件(redo log file)
核心原理:当提交一个事物,InnoDB存储引擎,必须完成
redo log
数据持久化,待事务 COMMIT 操作完成才算完成。另外重做日志还是满足幂等性。
重做日志块
重做日志是以512字节进行存储的。这意味着重做日志缓存、重做日志文件都是以块(block)的方式进行保存的,称之为重做日志块(redo log block),每块的大小为512字节。
若一个页中产生的重做日志数量大于512字节,那么需要分割为多个重做日志块进行存储。
重做日志块组成结构
重做日志相关参数
参数名 | 备注 | 默认值 |
---|---|---|
innodb_log_file_size | 重做日志文件大小 | 48M |
innodb_log_files_in_group | 指定重做日志文件组中文件的数量 | 2 |
innodb_log_group_home_dir | 指定日志文件组所在的路径 | ./ |
innodb_flush_log_at_trx_commit | 控制ACID日志刷新到磁盘策略 | 1 |
回滚日志
基本概念
当提交一个事务时,Innodb自动把修改前的数据备份到 redo log
中,当提交失败或者系统异常奔溃可通过 redo log
实现回滚。
注意:redo log 是逻辑回滚。
快照读
MySQL利用 redo log
实现了非锁定读
事务A 修改 ID = 1 数据,此时MySQL会对该资源进行锁定(独占锁)
事务B 查询 ID = 1 数据,此时就属于快照度。因为事务A 原始数据已经被备份到 redo log 中。
undo log 格式类别
insert undo log
insert undo log是在insert操作中产生的undo log。因为insert操作的记录,只对事务本身可见,对其他事务不可见(这是事务隔离性要求),故该undo log可以在事务提交后直接删除。不需要进行purge操作。
update undo log
update undo log记录的是对 delete
和 update
操作产生的undo log。因MVCC机制存在,所有不能在事务提交时就进行删除。提交时放入 undo log 链表,等待purge线程进行最后的删除。
为什么不能在事务提交后立马删除?
ID | 事务A | 事务B |
---|---|---|
1 | begin | begin |
2 | - | 删除ID=1数据 |
3 | - | commit |
4 | 查询ID=1数据 | |
5 | commit |
结论:如果事务B立马执行删除,这将导致事务A查不到任何数据,破坏了ACID特性。