mysql数据库隔离级别详解

发布时间:2023-02-25 17:30

目录
  • 隔离级别
    • 一、mysql有四个事务隔离级别
    • 二、为什么默认RR隔离级别?
    • 三、RR隔离级别下手动加锁解决幻读理论基础
  • 脏读、不可重复读、幻读 及其解决方法
    • 事务隔离级别命令行操作
      • 操作验证
        • 一、实现脏读
        • 二、操作验证--实现不可重复读
        • 三、操作验证--解决不可重复读
        • 四、操作验证--实现幻读
      • 总结

        隔离级别

        一、mysql有四个事务隔离级别

        每个级别都有字符或数字编号

        1. 读未提交 READ UNCOMMITTED | 0 : 存在脏读,不可重复度,幻读的问题。 
        2. 读已提交 READ COMMITTED | 1 : 解决脏读问题,存在不可重复读,幻读的问题。
        3. 可重复读 REPEATABLE READ | 2 : 解决脏读,不可重复读的问题,存在幻读,默认隔离级别,使用MVCC机制实现可重复读。
        4. 序列化 SERIALIZABLE | 3 : 解决脏读,不可重复读,幻读,可保证事务安全,但完全串行执行,性能最低。

        我有记忆方法,先是RU、RC, 记住UC顺序,联想到UC WEB。

        二、为什么默认RR隔离级别?

        RR级别作为mysql事务默认隔离级别,是事务完全和性能的折中。SERIALIZABLE级别是悲观地认为幻读时刻都会发生,故会自动地隐式地对事务所需资源加排他锁,其他事务访问此资源会被阻塞等待,故事务是安全的,但需要认值考虑性能。

        三、RR隔离级别下手动加锁解决幻读理论基础

        InnoDB的行锁锁定的是索引,而不是记录本身。索引映射的记录存在就加行锁,如果不存在则会加next-key lock/gap锁/间隙锁, 故InnoDB可以实现事务对某记录的预先占用。

        脏读、不可重复读、幻读 及其解决方法

        脏读

        • 一个事务读取到另一个事务还没有提交的数据。解决方法:把事务隔离级别调整到READ COMMITTED。

        不可重复读

        • 一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。解决方法:把事务隔离级别调整到REPEATABLE READ。

        幻读

        • 网上很多文章都说一个事务执行范围查询,两次select得到的条数不同,就叫幻读,这是错误的!!!
        • 幻读并不是说两次读取获取的结果集不同,幻读是指某一次select操作得到的结果所表征的数据状态无法支持后续的业务操作,具体例子:select某记录是否存在,不存在,准备插入此记录,但执行insert时发现此记录已存在,无法插入,此时就发生了幻读。
        • 还一种理解思路,就是因为先采用了\"快照读\",然后又用了\"当前读\",发现结果不同。比如先select是快照读,然后update、insert等,这时会用到当前读,发现操作出现未预料结果。

        幻读解决方法

        1、把事务隔离级别调整到SERIALIZABLE。2、RR隔离级别下,对select操作手动加行锁,select ... for update,这也序列化隔离级别下隐式会做的事。

        参考文章

        幻读  https://segmentfault.com/a/1190000016566788

        事务隔离级别命令行操作

        1、查看隔离级别

        1)查看当前会话隔离级别

        mysql> SELECT @@tx_isolation;
        +-----------------+
        | @@tx_isolation  |
        +-----------------+
        | REPEATABLE-READ |
        +-----------------+
        1 row in set, 1 warning (0.00 sec)

        2)查看系统隔离级别

        mysql> select @@global.tx_isolation;
        +-----------------------+
        | @@global.tx_isolation |
        +-----------------------+
        | READ-UNCOMMITTED      |
        +-----------------------+
        1 row in set, 1 warning (0.00 sec)

        2、设置隔离级别

        SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

        1)设置当前会话

        mysql> set session transaction isolation level repeatable read;
        Query OK, 0 rows affected (0.00 sec)

        2)设置系统

        mysql> set global transaction isolation  level read uncommitted;                
        Query OK, 0 rows affected (0.00 sec)3、命令行,开始事务时用

        操作验证

        自己在命令行去验证几种隔离级别下的读问题。

        一、实现脏读

        在不可提交读, 也就是READ UNCOMMITED情况下,会产生脏读。

        \"mysql数据库隔离级别详解_第1张图片\"

        二、操作验证--实现不可重复读

        在可提交读, 也就是READ COMMITED情况下,会产生不可重复读。

        \"mysql数据库隔离级别详解_第2张图片\"

        三、操作验证--解决不可重复读

        repeatable read(MySQL默认隔离级别),这时候能解决可重复读。

        右边事务提交了,修改了age=29,左边再次查询,还是28。

        \"mysql数据库隔离级别详解_第3张图片\"

        四、操作验证--实现幻读

        repeatable read(MySQL默认隔离级别),这时候还会出现幻读。

        \"mysql数据库隔离级别详解_第4张图片\"

        总结

        到此这篇关于mysql数据库隔离级别文章就介绍到这了,更多相关mysql隔离级别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

        ItVuer - 免责声明 - 关于我们 - 联系我们

        本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

        桂ICP备16001015号