从 ACID 到 MVCC,MySQL 事务与隔离级别超详解
⭐️所属专栏MySQL目录事务的基本概念什么是事务事务的典型问题火车票售票案例事务的ACID属性支持事务的存储引擎事务提交方式自动提交手动提交事务常见操作基本操作流程重要结论事务隔离级别读未提交 (Read Uncommitted)读提交 (Read Committed)可重复读 (Repeatable Read)串行化 (Serializable)隔离级别的查看与设置查看隔离级别设置隔离级别关键要点总结事务核心特性实际应用建议注意事项如何理解隔离性MVCC多版本并发控制概述MVCC实现原理快照读与当前读RR 与 RC的本质区别Read View结构可见性判断流程MySQL视图特性视图的基本操作创建视图查询视图修改视图数据删除视图视图的规则与限制视图的适用场景事务的基本概念什么是事务事务是一组DML语句组成的逻辑单元这些语句要么全部成功要么全部失败是一个整体保证数据操作的完整性和一致性事务的典型问题火车票售票案例客户端A检查票数0 → 准备卖票 客户端B检查票数0 → 准备卖票 客户端A更新票数-1 客户端B更新票数-1 结果同一张票被卖了两次事务的ACID属性原子性 (Atomicity)事务中的所有操作要么全部完成要么全部不完成不会结束在中间环节发生错误时回滚到事务开始前的状态一致性 (Consistency)事务开始前和结束后数据库完整性不被破坏写入数据必须完全符合预设规则隔离性 (Isolation)多个并发事务同时执行时互不干扰防止交叉执行导致的数据不一致持久性 (Durability)事务提交后对数据的修改是永久的即使系统故障也不会丢失支持事务的存储引擎InnoDB: 支持事务默认引擎MyISAM: 不支持事务-- 查看数据库引擎SHOWENGINES;事务提交方式自动提交SHOWVARIABLESLIKEautocommit;-- 查看自动提交状态SETAUTOCOMMIT0;-- 关闭自动提交SETAUTOCOMMIT1;-- 开启自动提交手动提交使用BEGIN或START TRANSACTION开始事务使用COMMIT提交事务使用ROLLBACK回滚事务事务常见操作基本操作流程BEGIN;-- 开始事务SAVEPOINTsave1;-- 设置保存点INSERTINTOaccountVALUES(1,张三,100);SAVEPOINTsave2;-- 设置保存点INSERTINTOaccountVALUES(2,李四,10000);ROLLBACKTOsave2;-- 回滚到保存点ROLLBACK;-- 回滚整个事务COMMIT;-- 提交事务重要结论输入BEGIN后必须通过COMMIT提交才会持久化事务可以手动回滚操作异常时MySQL自动回滚InnoDB中每条SQL默认封装成事务自动提交MyISAM不支持事务事务隔离级别读未提交 (Read Uncommitted)所有事务可以看到其他未提交事务的执行结果问题脏读、幻读、不可重复读实际生产中基本不使用读提交 (Read Committed)只能看到其他已提交事务的改变问题不可重复读大多数数据库的默认隔离级别非MySQL可重复读 (Repeatable Read)确保同一事务中多次读取看到相同数据解决了不可重复读问题MySQL通过Next-Key锁解决了幻读问题串行化 (Serializable)最高隔离级别强制事务排序解决所有并发问题但可能导致超时和锁竞争实际很少使用脏读读取到了另一个事务中修改但还未提交的数据不可重复读在同一个事务中多次读取同一数据得到的结果不同幻读一个事务内多次执行同一查询但另一个事务在两次查询之间插入或删除了符合条件的行导致两次查询结果不同隔离级别的查看与设置查看隔离级别SELECTglobal.tx_isolation;-- 查看全局隔离级别SELECTsession.tx_isolation;-- 查看当前会话隔离级别SELECTtx_isolation;-- 查看当前隔离级别设置隔离级别-- 设置会话隔离级别SETSESSIONTRANSACTIONISOLATIONLEVELREADUNCOMMITTED;SETSESSIONTRANSACTIONISOLATIONLEVELREADCOMMITTED;SETSESSIONTRANSACTIONISOLATIONLEVELREPEATABLEREAD;SETSESSIONTRANSACTIONISOLATIONLEVELSERIALIZABLE;-- 设置全局隔离级别SETGLOBALTRANSACTIONISOLATIONLEVELREADUNCOMMITTED;关键要点总结事务核心特性原子性保证操作的整体性一致性保证数据的正确性隔离性解决并发访问问题持久性保证数据的永久存储实际应用建议根据业务需求选择合适的隔离级别MySQL默认的RR级别在大多数场景下表现良好高并发场景注意锁竞争问题重要操作显式使用事务保证数据一致性注意事项只有InnoDB支持事务设置保存点可以实现部分回滚异常终止时未提交的事务会自动回滚提交后的数据修改具有持久性如何理解隔离性MVCC多版本并发控制概述MVCC是一种用来解决读-写冲突的无锁并发控制机制。它通过为事务分配单向增长的事务ID并为每个修改保存一个版本实现读操作不阻塞写操作写操作也不阻塞读操作从而提高数据库并发读写的性能。同时MVCC还能解决脏读、幻读、不可重复读等事务隔离问题但不能解决更新丢失问题。MySQL 的隔离级别核心就是通过 多版本并发控制MVCC 决定事务能看到数据的 “哪个版本”避免并发操作引发的脏读、不可重复读等问题。MVCC实现原理三个记录隐藏字段DB_TRX_ID6 byte最近修改修改/插入事务ID记录创建这条记录/最后一次修改该记录的事务ID。DB_ROLL_PTR7 byte回滚指针指向这条记录的上一个版本在undo log中。DB_ROW_ID6 byte隐含的自增ID隐藏主键如果数据表没有主键InnoDB会自动以DB_ROW_ID产生一个聚簇索引。undo日志MySQL在内存中运行所有机制索引、事务、隔离性、日志等在内存缓冲区中完成并在合适时刷新到磁盘。undo log是MySQL中的一段内存缓冲区用于保存日志数据实现写时拷贝。Read ViewRead View是事务进行快照读操作时生成的读视图记录并维护系统当前活跃事务的ID。用于可见性判断决定当前事务能看到哪个版本的数据。快照读与当前读快照读读取历史版本一般而言不受加锁限制提高效率。当前读读取最新的记录增删改操作都是当前读select也有可能当前读如select lock in share mode、select for update。RR 与 RC的本质区别RRREPEATABLE READ级别某个事务对某条记录的第一次快照读会创建一个快照及Read View记录此时所有其他活动事务的快照。此后该事务的快照读都使用同一个Read View对其他事务的修改不可见。RCREAD COMMITTED级别事务中每次快照读都会新生成一个快照和Read View因此可以看到别的事务提交的更新。每次快照读都会形成新的Read View导致不可重复读问题。Read View结构classReadView{private:trx_id_t m_low_limit_id;// 高水位大于等于这个ID的事务均不可见trx_id_t m_up_limit_id;// 低水位小于这个ID的事务均可见trx_id_t m_creator_trx_id;// 创建该Read View的事务IDids_t m_ids;// 创建视图时的活跃事务id列表trx_id_t m_low_limit_no;// 配合purge标识该视图不需要小于m_low_limit_no的UNDO LOGboolm_closed;// 标记视图是否被关闭};可见性判断流程拿当前记录的DB_TRX_ID与Read View中的up_limit_id、low_limit_id和活跃事务ID列表(m_ids)进行比较。如果DB_TRX_ID小于up_limit_id说明事务已提交可见。如果DB_TRX_ID大于等于low_limit_id说明事务在当前Read View生成后开启不可见。如果m_ids包含DB_TRX_ID说明事务未提交不可见。否则遍历下一个版本直到找到可见版本。MySQL视图特性视图是基于查询结果的虚拟表并非实际存储数据而是动态关联基表数据核心特性及用法如下虚拟性视图本身不存储数据数据来源于其定义的SELECT查询对应的基表双向联动视图的数据修改增删改会同步影响基表基表的数据变化也会实时反映到视图中简化性将复杂查询如多表关联、聚合计算封装为视图后续可直接像表一样查询降低使用复杂度。视图的基本操作创建视图createview视图名asselect语句;案例关联EMP和DEPT表封装“员工-部门”查询createviewv_ename_dnameasselectename,dnamefromEMP,DEPTwhereEMP.deptnoDEPT.deptno;查询视图与查询普通表完全一致可直接使用SELECTselect*fromv_ename_dnameorderbydname;修改视图数据对视图执行UPDATE/INSERT/DELETE会同步修改基表数据-- 修改视图中CLARK的姓名为TEST基表EMP的CLARK也会被修改updatev_ename_dnamesetenameTESTwhereenameCLARK;删除视图dropview视图名;视图的规则与限制命名唯一性视图名需唯一不能与当前数据库的表/其他视图重名性能影响复杂查询如多表关联、子查询封装为视图后多次查询可能影响性能功能限制视图不能添加索引、触发器、默认值并非所有视图都支持修改如包含聚合函数、DISTINCT、GROUP BY的视图无法执行增删改排序覆盖视图定义中的ORDER BY会被查询视图时的ORDER BY覆盖权限控制可通过视图开放部分数据的访问权限隐藏基表的敏感字段提升安全性。视图的适用场景简化复杂查询将多表关联、嵌套查询封装为视图后续直接调用数据权限控制仅向用户开放视图而非基表隐藏不需要展示的字段统一数据口径多个业务场景需使用相同的查询逻辑时用视图保证逻辑一致。避免对“复杂视图”执行修改操作易失败或引发数据异常视图依赖基表结构若基表字段被修改/删除视图可能失效需重新创建。本篇文章的分享就到这里了如果您觉得在本文有所收获还请留下您的三连支持哦~