网站LOGO
逐暗者的麦田
页面加载中
4月26日
网站LOGO 逐暗者的麦田
一个java软件攻城狮
菜单
  • 逐暗者的麦田
    一个java软件攻城狮
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    知识点整理(九)——mysql的MVCC
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    按住ctrl可打开默认菜单

    知识点整理(九)——mysql的MVCC

    shellingford · 原创 ·
    程序人生 · 知识点整理mysql
    共 2017 字 · 约 3 分钟 · 247
    本文最后更新于2023年08月07日,已经过了262天没有更新,若内容或图片失效,请留言反馈

    mysql事务控制

    并发事务

    并发事务会带来一些问题

    • 脏读
      一个事务读取到了另一个事务修改但未提交的数据。
    • 不可重复读
      一个事务中多次读取同一行记录不一致。
    • 幻读
      一个事务中多次按相同条件查询,结果不一致。(多了或者少了)

    事务隔离级别

    事务隔离级别脏读不可重复读幻读
    读未提交会发生会发生会发生
    读已提交×会发生会发生
    可重复读××会发生
    串行化×××

    注意mysql的MVCC解决了部分幻读问题(不能解决当前读下的幻读)。

    事务并发问题主要是解决读读、读写、写写之间的问题。加排它锁性能太低。使用读写锁能解决读读之间性能问题,但是无法解决读写之间的性能。

    MVCC

    MVCC使用了Copy On Write的思想。可以支持读读并行,也可以支持读写并行。写写依旧无法并行。

    概念

    MVCC(Multi Version Concurrency Control)被称为多版本控制。在数据库中为了实现高并发数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。

    MVCC最大的好处是读不加锁,读写不冲突,这对读多写少的系统非常重要。现阶段几乎所有关系型数据库都支持MVCC。mysql的MVCC只在读已提交和可重复读2种隔离级别下工作。

    实现原理

    • 快照读:读取快照版本,普通的select查询,不加锁。
    • 当前读:读取记录的最新版本,会加锁。(select for update / lock in share mode/insert/update/delete)
    • 事务id:mysql会维护一个全局事务id,每个事务都不一样,自增。

    当我们向mysql插入一条记录时,mysql会这么存储。(假设事务1)


    DATA_ROW_ID:隐藏数据ID
    DB_TRX_ID:当前事务版本号
    DB_ROLL_PT:回滚指针

    当我们修改这条记录后,mysql会这么存储。(假设事务10)

    再修改一下会变成这样。(假设事务15)

    mysql会把修改前的记录复制到undo log中,然后修改现有数据,设置当前事务id,设置回滚指针指向之前的记录行。

    具体如何实现可重复读呢?

    在事务开启时创建readView,之后只按照readView内容进行读取。这样就保证了可以重复读到相同快照内容。(注意事务开启时怎么理解?begin/start transaction时第一个快照读语句,而要立刻开启是start transaction with consistent snapshot)

    readView里有哪些东西呢?

    • m_ids,当前有哪些事务正在执行,且还没有提交,这些事务的 id 就会存在这里;
    • min_trx_id,是指 m_ids 里最小的值;
    • max_trx_id,是指m_ids 里最大的值;
    • creator_trx_id,每开启一个事务都会生成一个 ReadView,而 creator_trx_id 就是这个开启的事务的 id。
    1. 如果查到一条记录,其中的DB_TRX_ID小于min_trx_id,那么肯定可以看到这条数据。因为当前事务肯定在活动中,肯定大于min_trx_id,那么本事务开启时这个数据已经提交了。
    2. 如果查到一条记录,其中的DB_TRX_ID大于max_trx_id,那么这条数据肯定看不到。因为当前事务开启的时候记录所在的事务还没开启。这个时候应该通过回滚指针找到之前版本的记录进行判断。
    3. 如果查到一条记录,其中的DB_TRX_ID介于min_trx_id和max_trx_id之间,那就看是否在m_ids内,如果在,就表示本事务开始时,记录所在事务还没提交,所以不能看到,反之则能看到。
    声明:本文由 shellingford(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    发一条! 发一条!
    博客logo 逐暗者的麦田 一个java软件攻城狮
    MOEICP 萌ICP备20237379号 ICP 沪ICP备13037081号-2,沪ICP备13037081号-1,沪ICP备13037081号-3 又拍云 本站由又拍云提供CDN加速/云存储服务

    🕛

    本站已运行 2 年 243 天 23 小时 56 分

    🌳

    自豪地使用 Typecho 建站,并搭配 MyLife 主题
    逐暗者的麦田. © 2021 ~ 2024.
    网站logo

    逐暗者的麦田 一个java软件攻城狮
     
     
     
     
    壁纸