欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL事务隔离级别以及实现原理

程序员文章站 2022-05-04 12:45:31
...

一、事务完整性问题

脏读:可以读取其他事务未提交的数据,如果该事务回滚,则数据为错误数据。

不可重复读:A事务查看,B事务修改提交,A事务再次查看,数据不一样。

幻读:幻读与不可重复读相似,但不可重复读重点在于update和delete,幻读重点在于insert

t Session A                   Session B
|
| START TRANSACTION;          START TRANSACTION;
|
| SELECT * FROM t_bitfly;
| empty set
|                             INSERT INTO t_bitfly
|                             VALUES (1, 'a');
|
| SELECT * FROM t_bitfly;
| empty set
|                             COMMIT;
|
| SELECT * FROM t_bitfly;
| empty set
|
| INSERT INTO t_bitfly VALUES (1, 'a');
| ERROR 1062 (23000):
| Duplicate entry '1' for key 1
v (???刚刚明明告诉我没有这条记录的)

t Session A                  Session B
|
| START TRANSACTION;         START TRANSACTION;
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | a     |
| +------+-------+
|                            INSERT INTO t_bitfly
|                            VALUES (2, 'b');
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | a     |
| +------+-------+
|                            COMMIT;
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | a     |
| +------+-------+
|
| UPDATE t_bitfly SET value='z';
| Rows matched: 2  Changed: 2  Warnings: 0
| (怎么多出来一行)
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | z     |
| |    2 | z     |
| +------+-------+
|


二、事务隔离级别

MySQL事务隔离级别以及实现原理

    1. 读未提交(Read Uncommitted)

    原理:任何操作都不加锁

    2. 读提交(Read Commit)

原理:读操作不加锁,写操作加锁。读被加锁的数据时,读事务每次都读undo log中的最近版本,因此可能对同一数据读到不同的版本(不可重复读),但能保证每次都读到最新的数据。

    3. 可重复读(Reapable Read)

    原理:第一次读数据的时候就将数据加行锁(共享锁),使其他事务不能修改当前数据,即可实现可重复读。但是不能锁住insert进来的新的数据,当前事务读取或者修改的同时,另一个事务还是可以insert提交,造成幻读。

    4. 串行化(Serializable)

    原理:锁表,读锁和写锁阻塞。

三、InnoDB事务相关概念

●  redo log

    MySQL在开启事务时,会将执行的SQL保存到指定的log文件,即redo log。当MySQL执行recovery时执行redo log里的SQL操作即可。redo log不会被立即写入磁盘,会先写入redo buffer;当客户端执行commit时,redo buffer的内容会视情况存入磁盘。

●  undo log

    与redo log相反,undo log是为了回滚事务而写的日志,具体内容就是copy事务开始前的数据(行)到undo buffer。

    与redo buffer一样,undo buffer也是环形缓冲,当缓冲满的时候buffer内容会被刷新到磁盘。

    与redo log不同的是,undo log没有独立的磁盘文件,所有的undo log均被存在主ibd数据文件中(表空间)。