zoukankan      html  css  js  c++  java
  • mysql可重复读现象及原理分析

    mysql可重复读现象及原理分析

    一、可重复读

    我们先看看现象,再分析原理。我的mysql版本是5.5。

    下面是一张表,只有一条数据,并且我开启了事物

    此时,另一个事物将record加1,因此我在开启一个命令行客户端,执行下面的命令:

    成功加1之后,实际上,数据库中record肯定是2。

    然后回到之前的客户端,再查一次:

    没毛病,record还是1,果然是可重复读。有些人以为mysql的可重复读是通过行锁实现的,

    从上面可以知道,肯定不是,如果是的话,第一次select * from test的时候,id=1的记录就会加行锁,我都加行锁了,我还没提交,另外的事物是怎么update成功的。

    结论就是mysql使用的MVCC(多版本并发控制),MVCC详解可以看:https://blog.csdn.net/whoamiyang/article/details/51901888

    我们继续,我之前的第一个事物还没提交,不过提交之前,我也想加1;

    加完之后我再查一下,额,record是3,好像很奇怪,但也不奇怪。

    其实,update test set record=record+1 where id=1;这条语句中,在加1之前,他知道自己等于2,然后2+1=3。

    也就是说,update时读取数据是最新版本的数据,而select是到当前事物版本为止的数据。当更新成功之后,当前版本即为最新版本,再次select,读取的是最新的数据。

    在这里讨论下乐观锁的必要性。下面是乐观锁的实现,实现乐观锁,我们一般会这么做

    update test set record=record+1 where id=1 and record=1;

    如果不用乐观锁,你用select读取到的值其实根本不准确。除非你开启悲观锁,像下面这样:

    select * from test where id=1 for update;

    这样可以读取到最新的内容,同时在你当前的事物提交之前,其他事物的update此条记录将会锁等待。

    故事到此,还没有结束,此时我们开启事物三,也做加1操作看会发生什么。

    结果是,锁等待超时,也就是说(事物一)在更新完后,会加行锁,这个应该比较好理解。事物中,刚开始查询的时候是不会加行锁的,但是当有更新操作之后,会加行锁,直到事物提交。

    因为事务一还没有提交,所以事务三的select * from test;还只能查询到事务二提交的结果,也就是record是2   

    然后因为事务一中对id=1这条数据进行了修改,所以mysql自动将这条数据开启了行锁,在事务一提交之前,任何事务不可以修改id=1这条数据

    本文转自:

    mysql可重复读现象及原理分析 - mysql数据库栏目 - 红黑联盟
    https://www.2cto.com/database/201807/763885.html

  • 相关阅读:
    服务器安装软件
    SQL server
    改变下blog思维
    react 父子组件互相通信
    linux下,文件的权限和数字对应关系详解
    Linux 下非root用户使用docker
    Two 观察者 observer pattern
    one 策略模式 strategy
    ssm maven spring AOP读写分离
    Unknown column in 'where clause'
  • 原文地址:https://www.cnblogs.com/yuzhuang/p/11585774.html
Copyright © 2011-2022 走看看