数据库隔离级别为数据库事务四大基本特性:原子性、一致性、隔离性、持久性其中之一,并且是其中最难理解和重要的特性,这里对个人对于隔离级别的理解做出记录
测试过程中需要使用到的sql语句
#设置数据库隔离级别,但是需要注意的是此设置只对当前会话生效
set tx_isolation='READ-UNCOMMITTED';
#确认设置是否成功
select @@tx_isolation;
或者
show variables like 'tx_isolation';
#查询未提交事务
SELECT trx_mysql_thread_id
FROM information_schema.INNODB_TRX
#结束未提交事务
KILL ID
一、READ-UNCOMMITTED(未提交读):能够在当前事务中读取到其它未提交事务中更新的数据,当其它事务回滚后之前读到的数据变为脏数据,又称为脏读
事务1 | 事务2 | 结果 |
SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; UPDATE red_record SET total=6 WHERE id=1; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; SELECT * FROM red_record WHERE id=1; | 读取到了事务1中未提交的更新数据 | |
COMMIT; | ![]() | |
SELECT * FROM red_record WHERE id=1; | ![]() | |
COMMIT; |
二、READ-COMMITTED(提交读):当前事务只能读取到其它事务提交的数据,但是会出现同一个事务查询同一条记录结果不一样,又称为不可重复读
事务1 | 事务2 | 结果 |
SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; UPDATE red_record SET total=6 WHERE id=1; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
COMMIT; | ![]() | |
SELECT id,total FROM red_record WHERE id=1; | 出现同一个事务中对同一条记录读取的结果不一样 | |
COMMIT; |
三、REPEATABLE-READ(可重复读):保证了在同一个事务中多次读取同一条记录的结果保持一致,但是会出现幻读,当某个事务在读取某个范围内的数据时有新的记录插入,当再次读取这个范围内的数据时会出现幻行
事务1 | 事务2 | 结果 |
SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; UPDATE red_record SET total=6 WHERE id=1; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
COMMIT; | ![]() | |
SELECT id,total FROM red_record WHERE id=1; | ![]() | |
COMMIT; |
四、SERIALIZABLE(可串行化):SERIALIZABLE隔离级别最高,它是通过强制事务串行化执行,避免了前面说的幻读,会在读取的每一行数据上都加锁,所以会导致大量的超时和锁争用问
事务1 | 事务2 | 结果 |
BEGIN; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
BEGIN; SELECT id,total FROM red_record WHERE id=1; | ![]() | |
UPDATE red_record SET total=6 WHERE id=1; | 等待事务1提交 | |
COMMIT; | ||
COMMIT; | ![]() |