事务Transaction
1. 概念
- 一个最小的不可再分的工作单元
- 一个事务对应一个完整的业务逻辑
- 事务只和DML语句有关系,由批量的DML语句组成
2. 事务的四个特性(ACID)
Atomicity(原子性):事务是不可分割的。内部操作要么全成功,要么全失败。
Consistency(一致性):事务要求所有DML语句操作,必须保持同时成功或同时失败.
Isolation(隔离性):多个并发事务之间要相互隔离,不能有干扰。
Durability(持久性):事务一旦提交就会持久化数据(写入数据库并持久储存),并且不能回滚。
2.1. 原子性
确保原子性的方法是回滚。在MySQL中,回滚是通过回滚日志(Undo Log)实现的。回滚日志就是记录了你的多有操作的逆操作,当需要回滚时,就把这个事务的回滚日志里的操作全执行一次。
2.2. 一致性
事务执行的前后都是合法的数据状态,不会违背任何的数据完整性,这就是“一致”的意思。即在事务执行前后数据都应是正确无误,逻辑自洽,完整无缺的。
3. 隔离级别
3.1. read uncommitted(读未提交)
事务A先写数据,则事务B不允许同时进行写操作,但允许事务B读A未提交的此行数据,这里读到的数据称为脏数据,即脏读"Dirty Read"
底层:读不加锁,写加行级共享锁(可以读,无法修改和删除的一种数据锁,只能加共享锁)直到事务结束
3.2. read committed(读已提交)
事务A先写,事务B不能读,A提交后才能读此行数据
但可能出现不可重复读:即B前后两次读之间A修改了,导致不一致
底层:读时加行级共享锁,读完释放,写时加行级排它锁(不能加其他锁,获锁的事务可以读写)直到事务结束
3.3. repeatable read(可重复读)
事务A先写,事务B不能读写,A先读,B不能写
但可能产生幻读:即B前后两次读全表之间A插入了,导致不一致
底层:读时加行级共享锁,直到事务结束,写时加行级排他锁直到事务结束.
3.4. serializable(可串行化)
事务只能一个按顺序一个执行
底层:读时,加表级共享锁,直到事务结束,写时加表级排他锁直到事务结束.
隔离级别 | 脏读(Dirty read) | 不可重复读(Non-repeatable read) | 幻读(Phantom read) | 第一类丢失更新 | 第二类丢失更新 |
---|---|---|---|---|---|
READ UNCOMMITED | 允许 | 允许 | 允许 | 不允许 | 允许 |
READ COMMITED | 不允许 | 允许 | 允许 | 不允许 | 允许 |
REPEATABLE READ | 不允许 | 不允许 | 允许 | 不允许 | 不允许 |
SERIALIZBLE | 不允许 | 不允许 | 不允许 | 不允许 | 不允许 |
脏读:读取缓冲池中未提交的行数据就叫脏读,违反了事务的隔离性。
不可重复读:一个事务内,多次读到了其他已经提交的事务的更改(或删除)数据.对策:添加行级锁
幻读:一个事务内,多次读到了其他已提交事务的新增数据.对策:添加表级锁
第一类丢失更新:A事务回滚时覆盖了事务B已提交的数据
第二类丢失更新:A事务提交时覆盖了事务B已提交的数据
大部分数据库中使用提交读作为默认的隔离级别,这是出于性能和一致性的平衡,而MySQL中则默认采用可重复读作为配置。
4. 语法
4.1. 关闭/开启自动提交事务(只对当前会话有效)
set autocommit = off/on; 或者 set session autocommit = off/on;
4.2. 事务的使用
start transaction;或BEGIN
DML语句...
COMMIT; 成功时提交,持久化数据,事务终结.
ROLLBACK; 失败时回滚,记录的操作都失效.事务终结
4.3. 修改隔离级别
SET [无/session/global] transaction isolation level <isolation-level>
4.4. 查看隔离级别
SELECT @@[无/session/global].tx_isolation --会话/全局