mysql事务级别及可重复读/幻读情况模拟

mysql是大家常用的关系型数据存储数据库,为了保证一组操作的原子性(同时成功/同时失败)利用了事务。但是同一时间上读写可能存在的重复读、幻读/脏读等问题,就涉及到事务级别(默认级别:RR 可重复读 REPEATABLE-READ)设置。

事务级别分为:未提交可读(read uncommitted) 提交可读(read committed)可重复读(repeatable read)序列化(Serializable)

read uncommitted:事务未提交时即可读取,可能导致脏读。

read committed:事务提交后才可读取,但不可重复读(更新事务未提交前,其它查询为老值,但同一事务内存在更新前后查询不一致问题)(发生在update操作时)。

repeatable read: 可重复读,但是可能幻读(发生在insert操作时)。

幻读:A事务第一次查询时只存在一条,B事务新增一条记录,A事务再更新操作时更新成功两条。

幻读具体案例:

A事务:

SELECT * FROM `ims_user`;     #查询结果1条

B事务:

INSERT ims_user ( NAME,STATUS) VALUES( 'c3',3);   #新插入一条
COMMIT ;

A事务:

SELECT * FROM `ims_user`;#查询结果还是1条

UPDATE ims_user SET `status` = 4 WHERE `status`=3;  #更新结果2条。

COMMIT ;

可重复读/幻读产生原因分析:

1、mvcc版本控制:我们可以先插入,后查询则结果正常。

验证步骤:

B事务:

INSERT ims_user ( NAME,STATUS) VALUES( 'c3',3);   #新插入一条
COMMIT ;

 A事务:

              SELECT * FROM `ims_user`;#查询结果正常,新插入数据可查询到

                 2、无锁:“SELECT * FROM `ims_user`;”查询从快照中读,不存在锁。当发生“UPDATE/DELETE/INSERT”时为当前读,会产生行锁、表锁或者间隙锁(RR机制下)。

        解决方案:

             1、切换事务级别为Serializable。

             2、悲观锁:SELECT * FROM `ims_user` for update; 或者 共享锁:SELECT * FROM `ims_user` lock in share mode;

 

Serializable:序列化事务机制,串行处理任务。牺牲性能,保证数据。

 

其它:

查看当前事务级别:SELECT @@tx_isolation;

查看当前事务是否自动提交:show VARIABLES LIKE 'autocommit';

 

 lock in share mode

posted @ 2022-03-23 16:56  纵观  阅读(175)  评论(0编辑  收藏  举报