1. 概念
事务是一组操作的集合,事务会把所有操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
2. 开启事务
操作方式一:设置事务提交方式
-- 查看事务提交方式
SELECT @@AUTOCOMMIT;
-- 设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效
SET @@AUTOCOMMIT = 0;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
操作方式二:手动开启事务
开启事务:START TRANSACTION 或 BEGIN TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
回滚(Rollback)指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为。
3. 四大特性(ACID)
- 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败
- 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏,数据库只是从一种一致性状态转变为另一种一致性状态。
ACID一致性是指事务的执行不会破坏数据库的完整性约束,所谓的完整性约束包括数据关系的完整性和业务逻辑的完整性。因此,这里的“一致性”指的是完整性约束不会破坏。
- 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
- 持久性(Durability):事务处理结束后,对数据的修改是永久的
4. 并发事务带来的问题
4.1. 脏读(数据被其他事务弄脏了)
一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象
例如,事务A对data进行修改,但是并未提交,这时事务B读取data,读取的是A修改后的数据。但是之后事务A发生了回滚,那么事务B读取的数据就出现了问题,这种现象称为脏读
原因:在读未提交的隔离级别下,SELECT语句在不加锁的的模式下执行
SELECT statements are performed in a nonlocking fashion
MySQL :: MySQL 8.0 Reference Manual :: 17.7.2.1 Transaction Isolation Levels
解决办法:将事务的隔离级别设置为 read committed(读提交):指一个事务提交之后,它做的变更才能被其他事务看到
4.2. 不可重复读(前后不一致)
在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象
假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库中读取数据,然后继续执行代码逻辑处理,在这过程中如果事务 B 更新了这条数据,并提交了事务,那么当事务 A 再次读取该数据时,就会发现前后两次读到的数据是不一致的,这种现象就被称为不可重复读。
解决办法:将事务的隔离级别设置为 repeatable read(可重复读):指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的
4.3. 幻读(前后个数不一,仿佛出现了幻觉)
在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象
例如,事务A执行一个条件查询,满足该条件的记录有5条。在事务A的过程中,事务B又插入了一条满足该条件的记录,这时事务A再查询,就有6条满足该条件的记录,这种现象就称为幻读。
解决办法:在可重复读隔离级别下,快照读依靠MVCC机制解决幻读问题,当前读通过间隙锁解决幻读问题。
问题 | 描述 |
脏读 | 一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象 |
不可重复读 | 在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象 |
幻读 | 在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象 |