当前位置: 首页 > 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加锁;
    • 间隙锁:锁定的是两个索引区间,而不锁定具体的记录,主要用于解决幻读问题,防止在区间范围里面插入记录;
    • 临键锁:记录锁和间隙锁,不仅锁定行数据、也锁定区间范围

相关文章:

  • Spring AI 的功能介绍、集成使用和详细示例说明
  • 安卓中0dp和match_parent区别
  • SD框架下 LoRA 训练教程3-LORA学习率调度器(Learning Rate Scheduler)核心策略与实践指南
  • AI人工智能在教育领域的应用
  • 全球超精密机床市场深度分析:技术突破与新兴市场驱动的产业变革(2025-2031)
  • 在微创手术中使用Kinova轻型机械臂进行多视图图像采集和3D重建
  • 【专利信息服务平台-注册/登录安全分析报告】
  • 基于vue框架的订单管理系统r3771(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 游戏引擎学习第286天:开始解耦实体行为
  • 达梦数据库多版本并发控制(MVCC)_yxy
  • 【免疫荧光优选】APC 650/660nm 激发发射光谱,Elabscience F4/80 抗体点亮巨噬细胞研究!
  • 【Ansible基础】Ansible执行流程详解:从Playbook到实际任务
  • 【基础】Windows开发设置入门7:PowerShell的相关概念和使用
  • opencv入门指南
  • UI自动化测试中,一个完整的断言应所需要考虑的问题
  • Linux基础开发工具大全
  • IEC 60601-2-16:2025 标准解析
  • muduo库Poller模块详解
  • B2C 商城转型指南:传统企业如何用 ZKmall模板商城实现电商化
  • 在多个SpringBoot程序中./相对路径下隐患、文件覆盖问题
  • 大连三大网络推广网站/企业网站建设cms
  • jsp网站建设美食/广州百度推广代理公司
  • 具有营销型网站有哪些/搜索引擎搜索
  • 站长号/小程序搭建
  • 营销型网站建设大千建站/北京百度seo排名公司
  • 软件开发计划模板/佛山做seo推广公司