目录
一 . 什么是事务?
从概念上来讲,事务是一个有限的数据库操作序列构成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位 。
二. 事务的操作
使用以下SQL语句来开启并提交事务
# 开启一个事务
START TRANSACTION;
#设置保存点
savepoint point1;
# 多条 SQL 语句
SQL1,SQL2...
#回退事务到保存点
rollback to point1
#回退全部事务
rollback
## 提交事务,有事务操作生效,不能回退
COMMIT;
下面给出一个具体的事务提交的案例:
-- 1.创建一张测试表
CREATE TABLE t27(
id INT,
`name` VARCHAR(32));
-- 2.开始事务
START TRANSACTION
-- 3.设置保存点
SAVEPOINT a
-- 执行dml操作
INSERT INTO t27 VALUES(100,'tom');
SELECT * FROM t27;
SAVEPOINT b
-- 执行dml操作
INSERT INTO t27 VALUES(200,'jack');
-- 回退到b
ROLLBACK TO b
-- 继续回退 a
ROLLBACK TO a
-- 如果这样,表示直接回退到事务开始的状态
ROLLBACK
COMMIT
三. 事务的四大特性
- 原子性 : 事务作为一个整体执行,包含在其中的事务要么全部都执行,要么全部都不执行
- 隔离性:多个事务进行并发访问时,事务之间应该是相互隔离的,一个事务不应该被其他事务干扰,多个并发事务之间要相互隔离
- 持久性:事务完成进行提交时,对数据库所做的更改将永久性的保存在数据库中,即使数据库发生故障也不影响
- 一致性 : 指的是事务开始之前和事务结束只有,数据不会被破坏,假如A账户给B账户转账100元,无论成功与否,A和B的总金额是不发生改变的
InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?
- 持久性是通过 redo log (重做日志)来保证的;
- 原子性是通过 undo log(回滚日志) 来保证的;
- 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
- 一致性则是通过持久性+原子性+隔离性来保证;
四 . 并发事务可能产生的问题
- 脏读问题
当事务 A 在对数据进行修改的过程中, 事务 B 对同一个数据进行 了读取,此时 B 的读操作就叫做脏读,读取到的数据也被称之为脏数据 。
- 幻读问题
在同一组数据当中,事务 A 进行查询数据 , 事务 B 进行 插入新的数据,导致事务 A 再次进行相同的查询时,查询到的数据行数发生了改变,这种情况称之为幻读,幻读的解决方案一般为加间隙锁。
- 不可重复读问题
在同一组数据中,事务 A 进行查询数据, 事务B进行修改数据,导致事务A 重新执行相同的查询时,查询到的内容发生了改变,这种情况就称之为不可重复读,不可重复读的解决方案为加行锁或者表锁。
在这其中,不可重复读和幻读都是并发事务当中容易出现的问题,但是幻读主要涉及的是数据的插入,而不可重复读涉及的是数据的修改和更新,幻读的结果是前后读取的数据的数量不一致,而不可重复读是前后读取到的数据的内容不一致。
其中严重性 : 脏读 > 不可重复读 > 幻读
五 . 数据库的隔离级别
为了规避以上的三种并发事务中可能遇到的问题,MySQL 中提供了四种隔离级别来解决上述的并发事务问题,隔离级别越高,执行效率越低。
- 读未提交 :一个事务未提交时,但是他所做的变更就能够被其他事务所看到,即读未提交
- 读已提交: 一个事务提交之后,它所做的变更才能够被其他事务所看到,解决了脏读的问题
- 可重复读:同一个事务中,多次读取一个事务,获取到的结果是一致的, MySQL 的InnoDB引擎的默认隔离级别就是可重复读,但是没有解决幻读的问题。
- 串行化 :串行化会给记录加上读写锁,如果发生了读写冲突时,后访问的事务必须等待前一个事务执行完成,才能继续执行。
所以四种隔离级别的等级高低的排列如下 : 串行化 > 可重复读 > 读已提交 > 读未提交 ,隔离级别越低,事务请求的锁越InnoDB 存储引擎默认使用 可重复读
- 设置并查看当前事务的隔离级别
-- 查看当前会话隔离级别
SELECT @@tx_isolation;
-- 查看系统当前隔离级别
SELECT @@ global.tx_isplation
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
-- 设置系统当前隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL [设置你想设置的级别]
- MVCC
在MySQL InnoDB引擎层⾯,⼜有新的解决⽅案(解决加锁后读写性能问题),叫MVCC(Multi Version Concurrency Control) 多版本并发控制,它主要基于创建和维护数据的多个版本(或快照),以允许事务之间的并发执行而不会产生冲突。
在传统的锁定并发控制机制中,读操作和写操作之间会相互阻塞,因为写操作可能会改变数据,导致读操作的结果不一致。而MVCC通过创建数据的多个版本来解决这个问题。每个事务在开始时会创建一个一致性的数据库快照,然后在执行期间,事务只能看到在其开始之前已经存在的数据版本。这样,读操作可以并发地进行,而不会受到其他事务的写操作的影响 , 后续我们会对 MVCC 实现原理和锁机制进行详细的讲解说明 .