张成琦 新手冒险者
我很含蓄, 什么也没有留下!

浅谈 MYSQL - 事务

MYSQL数据中台2025-5-29 09:39 阅读 35 评论 0 热度 1

背景

本文旨在介绍mysql数据库事务隔离级别以及快照读的原理,帮助读者快速理解。

MYSQL 事务隔离级别

常见概念
  • 脏读
    • 读取到其他事务未提交数据

  • 不可重复读
    • 一次事务之中,同一条sql 的多次查询结果数据内容不一致

  • 幻读
    • 一次事务中,同一条sql多次执行的结果集中条数不一致
  • 快照读
    • 基于MVCC 的多版本并发控制,读操作不加锁。
  • 当前读
    • 语法: select ... for update,此时读操作会加 读锁(lock in shared model),读操作和写操作互斥
读未提交 ReadUncommit
  • 定义:
    • 各个事务可以读取到其他事务的未提交数据
读提交 ReadCommit (RC)
  • 定义:
    • 各个事务只能读取到其他事务已提交的数据
  • 特点:
    • 解决了脏读的问题。
    • oracle 的默认事务隔离级别
    • 此事务隔离级别下,不会开启间隙锁。
    • 尤其注意,当配置了主从同步时,binlog_format 应该设置为 row 以确保数据不会丢失
可重复读 RepeatableRead (RR)
  • 定义:
    • 一次事务之中,同一条sql 的多次查询结果数据内容一致
  • 特点:
    • 解决了不可重复读的问题(基于MVCC 机制)
    • 解决了幻读的 (基于next-key-lockgap-lock)
    • 是MYSQL 的默认隔离级别

MVCC 机制

  • 定义
    • MVCC (Muti Version Concurrency Control) ,多版本并发控制。是数据库管理系统中使用的一种并发控制方法,即读写冲突不加锁的解决方法
  • 实现原理
    • mysql 的 innodb主键索引 中存储的数据列上默认的会包含三个字段,隐式的row_id, 当前事务 trx_id, 指向undo_log 的roll_pointer (回滚指针)
    • readview存储当前活跃事物的数组id,用于和trx_i比较来确定数据可读版本。
      • 修改的事务id 小于数组中最小值的数据可读(意味着事务已经结束)
      • 修改的事务id 大于数组中最大值的数据不可读(意味着事务在本事务之后生成)
      • 修改的事务id 大于数组中最小值 且小于数值最大值的分两种情况
        • 修改的事务id 为当前事务id的可读(自己操作的数据自己可见,存在幻读bug)
        • 修改的事务id 在活跃的数组中的不可读(事务未结束),其余可读(实物已经结束)
    • rc和rr级别下区别:前者在每次执行的读sql时,生成一个新的事务id数组,而后者只会在事物的第一个select时生成一个不变的事务数组。

MySQL锁类型

  • 按加锁的对象和范围区分
    • 表锁
      • 整张表加锁,加锁效率高,支持并发度低,是myisam 引擎下默认加锁方式。
    • 行锁
      • 通过索引加锁,加锁效率低,并发度,条件过滤不能命中索引时,退化成表锁。
    • 间隙锁 
      • 锁定的是数据行之间的间隙,用于阻止特定数据区间的插入操作
    • 下一行锁 (next-key-lock
      • 等于行锁+间隙锁,mysq默认事物隔离级别为rr,就是通过 next-key-lock 来避免幻读。
  • 根据锁定是否共享
    • 共享锁 share
      • 读锁(快照读)
    • 排他锁 x
      • 写锁
      • 当前读:
        • select for update 
      • mdl 表锁
        • metadata lock: 对数据库加的全局写锁,此时阻塞数据库所有的读写进程,对表结构变更时会产生。线上环境需要慎重使用。


路过

雷人

握手
1

鲜花

刚表态过的朋友 (1 人)

评论

您需要登录后才可以发表言论 登录立即注册
facelist
  • 0帖子
  • 0关注
  • 0粉丝
  • 关注公众号
Copyright © 2025 鼎捷数智股份有限公司 版权所有 All Rights Reserved. Powered by Discuz! X5.0
关灯
即将开放
返回顶部
返回顶部