当前位置: 首页 > news >正文

MySQL中innodb的ACID

一、什么ACID

  • A:原子性,事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败回滚;
  • C:一致性,事务必须保证数据库从一个一致性的状态变换成另一个一致性的状态,如A给B转账50,A的余额扣减50,B的余额则一定要加50;
  • I:隔离性,多个并发执行的事务之间相互隔离,互不影响,根据不同的隔离级别会有不同的表现
  • D:一旦事务提交成功,其对数据库的更改就是永久的,即使系统发生故障(如断电、宕机),也不会丢失,通常通过日志机制(如 redo log)和定期刷盘来保证持久性。

二、Innodb怎么实现ACID的

  • 原子性:通过undolog实现,事务执行之前会记录undolog日志,事务回滚则通过undolog将数据恢复到事务开始前的状态;
  • 一致性:通过原子性、隔离性 和 持久性 的正确实现以及数据库设计中的完整性约束共同达成的。
  • 隔离性:通过事务的隔离级别实现(读未提交、读已提交、可重复读、串行化)
  • 持久性:redolog来实现,事务一旦提交,相关的Redo Log会被写入磁盘,即使系统在此之后崩溃,重启时也可以根据Redo Log恢复所有已完成的事务,保证了数据的持久性。

三、Innodb的隔离级别

  • 读未提交:一个事务读取了另一个事务还未提交的数据。会产生脏读、幻读、不可重复读;

  • 读已提交:通过MVCC和readView实现,在读已提交隔离级别下,在同一个事务中每次查询都会生成一个新的readView,从而能读取到其它事务已经提交的数据。解决了脏读,但是会存在不可重复读和幻读问题;

  • 可重复读:通过MVCC和readView实现,在可重复读隔离级别下,在同一个事务只有第1次查询会生成readView,后续的查询都使用相同的readView。解决了脏读、不可重复读,但是还会有脏读。结合LBCC来解决幻读问题;

  • 串行化:事务一个个的执行,解决了脏读、幻读、不可重复读问题,但是性能低下。

  • 脏读、幻读、不可重复读:

    • 脏读:一个事务读取了另一个事务还未提交的数据;
    • 不可重复读:同一个事务在两次查询同1记录的时候,由于别的事务在两次查询之间对该记录进行了修改,并提交,导致两次查询读取到同一记录的数据不一致;
    • 幻读:同一事务两次查询相同范围区间的记录,结果不一致,在两次查询之间,别的事务在该区间插入或删除了数据,导致两次查询相同范围的数据不一致。
  • 什么是MVCC:多版本并发控制,mysql为了提高读写并发性能,使用的一种无锁化的解决方案。
    mysql每行数据都有两个隐藏字段trx_id(事务id),roll_ptr(回滚指针),trx_id表示当前记录对应的事务id,roll_ptr则为当前记录的上一个版本,从而形成了一个版本链。

    • 什么是readView:readView有如下字段m_ids(当前存活的事务id)、creator_trx_id(创建readVied的事务id)、up_limit_id(m_ids中最小的事务id)、low_limit_id(j即将要分配的事务id);
    • 通过readView中的字段可以得到MVCC中哪些数据版本对当前事务可见:
      如:m_ids为 [1, 8, 9, 20]、creator_trx_id为10、up_limit_id为1 、low_limit_id为25、 trx_id为10
      那MVCC中各版本对应的trx_id与readView中的字段进行比较
      如果 trx_id == creator_trx_id,可见,因为该版本是由当前事务创建;
      如果 trx_id < up_limit_id(min_trx_id) 可见,因为trx_id小于当前readView中的最小事务id,说明创建该readView的时候trx_id对应的事务已经提交;
      如果 trx_id >= low_limit_id(max_trx_id) 不可见,说明trx_id对应的事务是在当前事务之后启动的,或未开始;
      如果up_limit_id < trx_id < low_limit_id ,如果trx_id在m_ids里面,则说明生成该版本的事务还未提交,当前事务并不可见,如果trx_id不在m_ids里面,说明生成该版本的事务已经提交,因此该版本对当前事务可见。

四、Innodb为了解决可重复读隔离级别下的幻读问题,通过结合LBCC实现

  • innodb中锁的分类:表锁、行锁、意向锁、间隙锁、临键锁、共享锁(读锁)、排他锁(写锁)
    • 表锁:因为innodb是基于索引加锁,即使当没有使用索引或需要进行全表扫描的时候,也会对每行数据加行锁,只有显示加表锁才会锁表,性能差。如LOCK TABLES t_user WRITE;
    • 行锁:记录锁锁定的是当前数据行
    • 意向锁:是为了提高加锁性能,不管是加行锁、读锁还是其余的锁都会先加意向锁。比如如果事务A想对表user加表锁,如果没有意向锁,则需要对user表中的每条记录进行遍历,如果所有的记录都没加锁,才能让事务A加表锁,不然会出现死锁等问题,这样性能很低,为了提升加速效率,才引入了意向锁。事务A想对user表加表锁,只需要判断该表是否加了意向锁即可,而不用全表扫描。
    • 共享锁:读锁,读锁和读锁可以共存即1行数据可以被加多个读锁,SELECT … LOCK IN SHARE MODE加共享锁;
    • 排他锁:互斥锁、写锁,可使用SELECT … FOR UPDATE加锁;
    • 间隙锁:锁定的是两个索引区间,而不锁定具体的记录,主要用于解决幻读问题,防止在区间范围里面插入记录;
    • 临键锁:记录锁和间隙锁,不仅锁定行数据、也锁定区间范围
http://www.xdnf.cn/news/479755.html

相关文章:

  • python中函数定义下划线代表什么意思,一个下划线,两个下划线什么意思
  • entity线段材质设置
  • 学习以任务为中心的潜动作,随地采取行动
  • Elasticsearch 分词与字段类型(keyword vs. text)面试题
  • 深入浅出 MinIO:身份管理与权限配置实战 !
  • AI与产品架构设计系列(2):Agent系统的应用架构与落地实
  • GpuGeek 网络加速:破解 AI 开发中的 “最后一公里” 瓶颈
  • vhca_id 简介,以及同 pf, vf 的关系
  • QT6 源(103)篇三:阅读与注释 QPlainTextEdit,给出源代码
  • 基于OpenCV的SIFT特征匹配指纹识别
  • 基于 CSS Grid 的网页,拆解页面整体布局结构
  • MCP协议的核心机制和交互过程
  • Review --- 框架
  • #跟着若城学鸿蒙# web篇-获取定位
  • 医学图像分析中的大规模基准测试与增强迁移学习|文献速递-深度学习医疗AI最新文献
  • 2025蓝桥杯JAVA编程题练习Day8
  • Java 后端给前端传Long值,精度丢失的问题与解决
  • 【pbootcms】打开访问首页显示未检测到您服务器环境的sqlite3数据库拓展,请检查php.ini中是否已经开启该拓展
  • 职业院校物联网安装调试员(工业数智技术)实训解决方案
  • 股指期货贴水为何会产生成本?
  • OceanBase 的系统变量、配置项和用户变量有何差异
  • 快速通关双链表秘籍
  • 旧 docker 版本通过 nvkind 搭建虚拟多节点 gpu 集群的坑
  • 智能裂变引擎 商业增长利器 —— 专业推客系统耀世而来
  • 图像对比度调整(局域拉普拉斯滤波)
  • 电子学会Python一级真题总结2
  • PHP 与 面向对象编程(OOP)
  • [250516] OpenAI 升级 ChatGPT:GPT-4.1 及 Mini 版上线!
  • 使用pytest实现参数化后,控制台输出的日志是乱码
  • 数学复习笔记 12