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

  • 相关阅读:
    使用 ASP.NET Core MVC 创建 Web API(五)
    使用 ASP.NET Core MVC 创建 Web API(四)
    使用 ASP.NET Core MVC 创建 Web API(三)
    使用 ASP.NET Core MVC 创建 Web API(二)
    使用 ASP.NET Core MVC 创建 Web API(一)
    学习ASP.NET Core Razor 编程系列十九——分页
    学习ASP.NET Core Razor 编程系列十八——并发解决方案
    一个屌丝程序猿的人生(九十八)
    一个屌丝程序猿的人生(九十七)
    一个屌丝程序猿的人生(九十五)
  • 原文地址:https://www.cnblogs.com/yuzhuang/p/11585774.html
Copyright © 2011-2022 走看看