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

【MySQL全面教学】MySQL事务与ACID Day9(2026年)

写在前面欢迎来到MySQL系列教学第9天今天我们将深入MySQL最核心的话题之一——事务Transaction。事务是保证数据库数据一致性和完整性的基石理解事务机制对于开发高可靠性的应用系统至关重要。无论你是刚接触数据库的新手还是准备面试的求职者这篇文章都将帮助你全面掌握MySQL事务的核心概念和原理。文章目录写在前面一、什么是事务1.1 事务的定义1.2 银行转账的例子1.3 事务的四个特性ACID二、ACID特性详解2.1 原子性Atomicity2.2 一致性Consistency2.3 隔离性Isolation2.4 持久性Durability三、事务控制语句3.1 基本语法3.2 SAVEPOINT保存点3.3 自动提交模式3.4 隐式提交四、事务隔离级别4.1 四种隔离级别4.2 设置隔离级别4.3 READ UNCOMMITTED读未提交4.4 READ COMMITTED读已提交4.5 REPEATABLE READ可重复读4.6 SERIALIZABLE串行化五、并发问题详解5.1 脏读Dirty Read5.2 不可重复读Non-repeatable Read5.3 幻读Phantom Read5.4 三种并发问题对比六、MVCC多版本并发控制6.1 什么是MVCC6.2 核心概念6.3 快照读 vs 当前读6.4 ReadView的工作原理6.5 MVCC实现可重复读七、实战电商下单的事务处理7.1 业务场景7.2 事务设计7.3 调用示例八、踩坑提醒8.1 长事务问题8.2 事务中避免调用外部接口8.3 注意死锁九、面试高频考点Q1四种隔离级别分别解决什么问题Q2MySQL默认的隔离级别是什么为什么Q3幻读是怎么产生的如何解决Q4MVCC是如何工作的Q5事务的ACID是如何保证的十、总结下一步预告参考资料互动话题一、什么是事务1.1 事务的定义事务是一组逻辑上的数据库操作这些操作要么全部成功执行要么全部不执行。事务是数据库管理系统执行过程中的一个逻辑单位。1.2 银行转账的例子最经典的事务例子就是银行转账张三给李四转账1000元需要两个操作 1. 张三账户余额减少1000元 2. 李四账户余额增加1000元 这两个操作必须同时成功或同时失败 - 如果第1步成功第2步失败张三的钱少了李四没收到钱凭空消失了 - 如果第1步失败第2步成功李四凭空多了1000元 这两种情况都是不可接受的-- 事务示例STARTTRANSACTION;-- 1. 扣减张三的余额UPDATEaccountsSETbalancebalance-1000WHEREname张三;-- 2. 增加李四的余额UPDATEaccountsSETbalancebalance1000WHEREname李四;-- 检查是否都成功IF(没有错误)THENCOMMIT;-- 提交事务永久保存修改ELSEROLLBACK;-- 回滚事务撤销所有修改ENDIF;1.3 事务的四个特性ACID特性英文含义说明原子性Atomicity不可再分事务是最小执行单位要么全做要么全不做一致性Consistency数据一致事务执行前后数据库从一个一致状态变为另一个一致状态隔离性Isolation互不干扰并发执行的事务互不干扰持久性Durability永久保存事务一旦提交修改永久生效二、ACID特性详解2.1 原子性Atomicity定义事务是一个不可分割的最小工作单元事务中的所有操作要么全部成功要么全部失败回滚。实现机制undo log回滚日志记录事务执行前的数据状态用于回滚-- 原子性示例STARTTRANSACTION;INSERTINTOorders(user_id,amount)VALUES(1,100);-- 成功INSERTINTOorder_items(order_id,product_id)VALUES(LAST_INSERT_ID(),1);-- 成功UPDATEproductsSETstockstock-1WHEREid1;-- 假设这里库存不足失败-- 由于第3步失败前面两步自动回滚ROLLBACK;2.2 一致性Consistency定义事务执行前后数据库必须处于一致性状态。所有数据必须满足预定义的完整性约束外键、唯一约束、CHECK约束等。示例-- 转账前后系统总金额应该不变-- 转账前张三5000 李四3000 8000-- 转账后张三4000 李四4000 8000-- 一致性检查CREATETABLEaccounts(idINTPRIMARYKEY,nameVARCHAR(50),balanceDECIMAL(10,2)CHECK(balance0)-- 余额不能为负);-- 如果执行 UPDATE accounts SET balance balance - 1000 WHERE balance 1000;-- 会违反CHECK约束事务回滚保证一致性2.3 隔离性Isolation定义多个事务并发执行时一个事务的执行不应影响其他事务的执行。事务之间是相互隔离的。实现机制锁机制排他锁、共享锁MVCC多版本并发控制-- 事务ASTARTTRANSACTION;UPDATEaccountsSETbalancebalance-1000WHEREid1;-- 此时事务A未提交-- 事务B同时执行STARTTRANSACTION;SELECTbalanceFROMaccountsWHEREid1;-- 根据隔离级别不同可能读到不同的值2.4 持久性Durability定义事务一旦提交其对数据库的修改就是永久性的即使系统发生故障也不会丢失。实现机制redo log重做日志记录事务对数据的修改用于崩溃恢复binlog二进制日志用于数据恢复和主从复制三、事务控制语句3.1 基本语法-- 开启事务STARTTRANSACTION;-- 或BEGIN;-- 提交事务COMMIT;-- 回滚事务ROLLBACK;3.2 SAVEPOINT保存点STARTTRANSACTION;INSERTINTOaccounts(name,balance)VALUES(王五,1000);SAVEPOINTsp1;-- 设置保存点INSERTINTOaccounts(name,balance)VALUES(赵六,2000);SAVEPOINTsp2;-- 发现第二个插入有问题回滚到sp1ROLLBACKTOsp1;-- 继续其他操作INSERTINTOaccounts(name,balance)VALUES(孙七,3000);COMMIT;-- 最终只有王五和孙七被插入3.3 自动提交模式-- 查看自动提交状态SHOWVARIABLESLIKEautocommit;-- 关闭自动提交SETautocommit0;-- 此时每个SQL都在事务中需要手动COMMIT或ROLLBACKUPDATEaccountsSETbalance1000WHEREid1;-- 其他会话看不到这个修改直到执行COMMITCOMMIT;-- 开启自动提交默认SETautocommit1;3.4 隐式提交某些SQL语句会自动提交当前事务DDL语句CREATE、DROP、ALTER锁定语句LOCK TABLES、UNLOCK TABLESSTARTTRANSACTION;INSERTINTOusers(name)VALUES(张三);CREATETABLEtest(idINT);-- 隐式提交前面的INSERT被提交了ROLLBACK;-- 无效事务已经提交四、事务隔离级别4.1 四种隔离级别隔离级别脏读不可重复读幻读READ UNCOMMITTED可能可能可能READ COMMITTED不可能可能可能REPEATABLE READ不可能不可能可能SERIALIZABLE不可能不可能不可能4.2 设置隔离级别-- 查看当前隔离级别SELECTtransaction_isolation;-- 设置会话隔离级别SETSESSIONTRANSACTIONISOLATIONLEVELREADCOMMITTED;-- 设置全局隔离级别SETGLOBALTRANSACTIONISOLATIONLEVELREPEATABLEREAD;4.3 READ UNCOMMITTED读未提交特点事务可以读取其他事务未提交的数据。-- 事务ASTARTTRANSACTION;UPDATEaccountsSETbalance900WHEREid1;-- 未提交-- 事务BREAD UNCOMMITTEDSTARTTRANSACTION;SELECTbalanceFROMaccountsWHEREid1;-- 读到900脏读-- 事务A回滚ROLLBACK;-- 事务B读到的900就是脏数据问题脏读Dirty Read4.4 READ COMMITTED读已提交特点事务只能读取其他事务已提交的数据。-- 事务ASTARTTRANSACTION;UPDATEaccountsSETbalance900WHEREid1;-- 未提交-- 事务BREAD COMMITTEDSTARTTRANSACTION;SELECTbalanceFROMaccountsWHEREid1;-- 读到1000原值-- 事务A提交COMMIT;-- 事务B再次查询SELECTbalanceFROMaccountsWHEREid1;-- 读到900新值-- 同一事务内两次读取结果不同不可重复读问题不可重复读Non-repeatable Read4.5 REPEATABLE READ可重复读特点同一事务内多次读取同一数据结果一致。MySQL默认隔离级别。-- 事务ASTARTTRANSACTION;SELECTbalanceFROMaccountsWHEREid1;-- 读到1000-- 事务BSTARTTRANSACTION;UPDATEaccountsSETbalance900WHEREid1;COMMIT;-- 事务A再次查询SELECTbalanceFROMaccountsWHEREid1;-- 仍然读到1000可重复读COMMIT;实现原理MVCC机制使用事务开始时的数据快照。4.6 SERIALIZABLE串行化特点最高隔离级别强制事务串行执行完全避免并发问题。-- 事务ASTARTTRANSACTION;SELECT*FROMaccountsWHEREbalance500;-- 事务BSERIALIZABLESTARTTRANSACTION;INSERTINTOaccounts(name,balance)VALUES(新用户,1000);-- 阻塞等待事务A提交问题性能最差并发度最低。五、并发问题详解5.1 脏读Dirty Read定义事务读取了其他事务未提交的数据如果那个事务回滚读取到的数据就是无效的。-- 时间线-- T1: 事务A开始修改数据但未提交-- T2: 事务B读取了A修改后的数据-- T3: 事务A回滚-- T4: 事务B使用的数据是无效的解决方案使用READ COMMITTED或更高隔离级别。5.2 不可重复读Non-repeatable Read定义同一事务内两次读取同一数据结果不同被其他事务修改并提交。-- 时间线-- T1: 事务A读取数据X 100-- T2: 事务B修改X 200并提交-- T3: 事务A再次读取X 200与T1不同解决方案使用REPEATABLE READ或SERIALIZABLE。5.3 幻读Phantom Read定义同一事务内两次执行相同条件的查询返回的行数不同被其他事务插入或删除。-- 事务ASTARTTRANSACTION;SELECT*FROMaccountsWHEREbalance500;-- 返回3条-- 事务B插入新数据并提交INSERTINTOaccounts(name,balance)VALUES(新用户,1000);-- 事务A再次查询SELECT*FROMaccountsWHEREbalance500;-- 返回4条幻读解决方案SERIALIZABLE隔离级别InnoDB的间隙锁Gap Lock和临键锁Next-Key Lock5.4 三种并发问题对比问题描述发生条件解决方案脏读读到未提交数据READ UNCOMMITTEDREAD COMMITTED不可重复读同一事务两次读取结果不同READ COMMITTEDREPEATABLE READ幻读同一事务两次查询行数不同REPEATABLE READSERIALIZABLE六、MVCC多版本并发控制6.1 什么是MVCCMVCCMulti-Version Concurrency Control是一种并发控制技术通过保存数据的历史版本实现读写不阻塞提高并发性能。6.2 核心概念隐藏字段DB_TRX_ID最后修改该记录的事务IDDB_ROLL_PTR回滚指针指向undo logDB_ROW_ID隐藏主键如果没有显式主键undo log记录数据修改前的版本形成版本链用于回滚和MVCCReadView事务快照记录当前活跃事务ID列表用于判断数据版本对当前事务是否可见6.3 快照读 vs 当前读快照读Snapshot Read-- 普通SELECT就是快照读SELECT*FROMaccountsWHEREid1;-- 读取的是历史版本不加锁当前读Current Read-- 读取最新版本需要加锁SELECT*FROMaccountsWHEREid1FORUPDATE;-- 排他锁SELECT*FROMaccountsWHEREid1LOCKINSHAREMODE;-- 共享锁-- DML语句也是当前读INSERTINTOaccounts...UPDATEaccounts...DELETEFROMaccounts...6.4 ReadView的工作原理ReadView包含以下信息creator_trx_id创建该ReadView的事务IDm_ids生成ReadView时活跃的事务ID列表min_trx_idm_ids中的最小值max_trx_id下一个要分配的事务ID可见性判断规则如果DB_TRX_ID等于creator_trx_id可见自己修改的如果DB_TRX_ID小于min_trx_id可见事务已提交如果DB_TRX_ID大于等于max_trx_id不可见事务未开始如果DB_TRX_ID在m_ids中不可见事务未提交否则可见事务已提交6.5 MVCC实现可重复读-- 事务A事务ID100STARTTRANSACTION;-- 生成ReadView: m_ids[100], min_trx_id100, max_trx_id101SELECT*FROMaccountsWHEREid1;-- 读取快照-- 事务B事务ID101修改并提交UPDATEaccountsSETbalance900WHEREid1;COMMIT;-- 事务A再次查询使用相同的ReadViewSELECT*FROMaccountsWHEREid1;-- 仍然读到原值实现可重复读COMMIT;七、实战电商下单的事务处理7.1 业务场景用户下单需要完成以下操作创建订单记录扣减商品库存扣减用户余额创建订单明细7.2 事务设计-- 存储过程创建订单DELIMITER$$CREATEPROCEDUREcreate_order(INp_user_idBIGINT,INp_product_idBIGINT,INp_quantityINT,OUTp_order_idBIGINT,OUTp_resultVARCHAR(100))BEGINDECLAREv_priceDECIMAL(10,2);DECLAREv_stockINT;DECLAREv_balanceDECIMAL(12,2);DECLAREv_totalDECIMAL(12,2);DECLAREEXITHANDLERFORSQLEXCEPTIONBEGINROLLBACK;SETp_result订单创建失败已回滚;RESIGNAL;END;-- 开启事务STARTTRANSACTION;-- 1. 查询商品信息加排他锁防止并发修改SELECTprice,stockINTOv_price,v_stockFROMproductsWHEREidp_product_idFORUPDATE;-- 检查库存IFv_stockp_quantityTHENROLLBACK;SETp_result库存不足;SIGNAL SQLSTATE45000SETMESSAGE_TEXT库存不足;ENDIF;-- 2. 查询用户余额SELECTbalanceINTOv_balanceFROMusersWHEREidp_user_idFORUPDATE;SETv_totalv_price*p_quantity;-- 检查余额IFv_balancev_totalTHENROLLBACK;SETp_result余额不足;SIGNAL SQLSTATE45000SETMESSAGE_TEXT余额不足;ENDIF;-- 3. 扣减库存UPDATEproductsSETstockstock-p_quantityWHEREidp_product_id;-- 4. 扣减余额UPDATEusersSETbalancebalance-v_totalWHEREidp_user_id;-- 5. 创建订单INSERTINTOorders(user_id,total_amount,status,created_at)VALUES(p_user_id,v_total,1,NOW());SETp_order_idLAST_INSERT_ID();-- 6. 创建订单明细INSERTINTOorder_items(order_id,product_id,quantity,price)VALUES(p_order_id,p_product_id,p_quantity,v_price);-- 提交事务COMMIT;SETp_result订单创建成功;END$$DELIMITER;7.3 调用示例-- 调用存储过程创建订单SETorder_id0;SETresult;CALLcreate_order(1,100,2,order_id,result);SELECTorder_id,result;八、踩坑提醒8.1 长事务问题问题事务执行时间过长会导致锁持有时间过长阻塞其他事务undo log堆积影响性能可能导致死锁解决方案-- 1. 尽量缩短事务范围STARTTRANSACTION;-- 只放必要的操作COMMIT;-- 2. 避免在事务中执行耗时操作-- 错误事务中调用外部API、发送邮件等STARTTRANSACTION;INSERTINTOorders...;-- 发送邮件耗时操作不应该在事务中send_email();COMMIT;-- 正确先提交事务再发送邮件STARTTRANSACTION;INSERTINTOorders...;COMMIT;send_email();8.2 事务中避免调用外部接口-- 危险操作STARTTRANSACTION;UPDATEaccountsSETbalancebalance-100WHEREid1;-- 调用支付接口可能超时、失败CALLexternal_payment_api();-- 如果接口超时事务一直不提交锁一直不释放COMMIT;正确做法先调用外部接口接口成功后再开启事务更新数据库或者使用本地消息表实现最终一致性8.3 注意死锁-- 事务ASTARTTRANSACTION;UPDATEaccountsSETbalance900WHEREid1;-- 锁住id1UPDATEaccountsSETbalance1900WHEREid2;-- 等待id2-- 事务B同时执行STARTTRANSACTION;UPDATEaccountsSETbalance800WHEREid2;-- 锁住id2UPDATEaccountsSETbalance1800WHEREid1;-- 等待id1死锁解决方案按固定顺序访问资源设置锁超时时间捕获死锁异常并重试九、面试高频考点Q1四种隔离级别分别解决什么问题答READ UNCOMMITTED无性能最好问题最多READ COMMITTED解决脏读REPEATABLE READ解决脏读、不可重复读MySQL默认SERIALIZABLE解决脏读、不可重复读、幻读性能最差Q2MySQL默认的隔离级别是什么为什么答默认隔离级别是REPEATABLE READ可重复读原因相比READ COMMITTED避免了不可重复读问题InnoDB通过MVCC和间隙锁在REPEATABLE READ下也能解决幻读问题平衡了数据一致性和并发性能Q3幻读是怎么产生的如何解决答产生原因一个事务在两次查询同一范围数据时由于其他事务插入新数据导致两次查询结果行数不同。解决方案SERIALIZABLE隔离级别性能差InnoDB的间隙锁Gap Lock和临键锁Next-Key Lock查询时加FOR UPDATE锁定范围Q4MVCC是如何工作的答每行数据有隐藏字段DB_TRX_ID事务ID、DB_ROLL_PTR回滚指针修改数据时将旧版本存入undo log形成版本链事务开始时生成ReadView记录当前活跃事务查询时根据ReadView判断数据版本是否可见实现读写不阻塞提高并发性能Q5事务的ACID是如何保证的答原子性undo log实现回滚一致性原子性隔离性持久性共同保证加上约束检查隔离性锁机制MVCC持久性redo logbinlog实现崩溃恢复十、总结今天我们深入学习了MySQL事务的核心知识事务概念ACID特性是事务的基石事务控制START TRANSACTION、COMMIT、ROLLBACK、SAVEPOINT隔离级别四种隔离级别及其解决的问题并发问题脏读、不可重复读、幻读的产生和解决MVCC机制多版本并发控制实现高效读写分离实战应用电商下单的事务设计核心要点理解ACID是理解事务的基础选择合适的隔离级别平衡一致性和性能MVCC是InnoDB高并发的核心避免长事务和事务中调用外部接口下一步预告Day10我们将学习MySQL的锁机制与并发控制深入探讨InnoDB的各种锁类型记录锁、间隙锁、临键锁以及如何处理死锁问题。敬请期待参考资料MySQL官方文档 - 事务互动话题你在项目中遇到过哪些事务相关的问题是如何解决的你们项目使用的是什么隔离级别为什么选择这个级别对于分布式事务你有什么实践经验或了解欢迎在评论区分享你的经验和见解如果觉得本文有帮助别忘了点赞收藏哦~
http://www.gsyq.cn/news/1396595.html

相关文章:

  • 高校论文查重新规落地倒计时(2024Q3全面启用AI行为识别引擎):你还在用“同义词替换”?这4种伪规避已触发红色预警
  • 无锡GEO优化公司哪家口碑最好?(含维度说明+问题解答) - wxxwlm
  • 量子纠错新突破:基于神经网络的表面码解码器硬件实现与性能权衡
  • 2026年5月厦门财产分割律师服务能力测评:3家律所处理水平对比 - 奔跑123
  • 基于图注意力网络的医疗欺诈检测:从关系网络挖掘共谋团伙
  • cartopy 绘制中国地图:从基础边界到南海诸岛与十段线的完整实践
  • 手机本地部署Gemma 4大模型:离线AI助手的完整实践指南
  • go: N-Barrier Pattern
  • 南京少儿围棋考级培训推荐:南京棋院考级专长 - 19120507004
  • gitlab的一些使用异常记录
  • AI 智能体实训室:从大模型到教学落地的全链路实践
  • 2026 AI搜索优化白皮书:品牌信任链的重构与交付标准 - 资讯速览
  • 中小团队如何利用Taotoken实现多模型API的成本优化与统一调度
  • 2026 土工布工厂哪家批发最优惠:恒全土工材料批量特惠 - 13425704091
  • 30亿GEO市场谁在领跑?2026年GEO优化公司综合权威实力排行榜 - GEO优化
  • 南京少儿围棋考级培训排名:南京棋院榜单领先 - 13724980961
  • 中山琪朗丨2026 精选推荐・实力工厂,酒店灯饰定制 + 高端定制灯饰 - 资讯速览
  • cc/ds教学,计算机小白笔记(2.2)
  • 3步解锁网盘直链下载:一站式跨平台文件获取终极方案
  • 点云扫描 vs 高斯重建:数字孪生别再乱选!一个落地、一个只能看
  • AI大模型三种部署方式与企业落地全解析
  • 昇腾NPU上的NumPy兼容层:asnumpy如何让Python代码自动加速3倍
  • 【2026年郑州再生资源回收口碑推荐】 - 资讯速览
  • 【Lovable平台开发生死线】:3类致命本地化缺陷、5个合规雷区、1套GDPR+ISO 17100双认证落地模板
  • 5分钟掌握Zotero Style:让文献管理变得优雅高效的终极指南
  • 如何获取Reddit API credentials?(无法获取了)
  • 决策树算法|ID3、C4.5、CART区别详解
  • 避开 Agent 落地大坑,业内大咖复盘行业真相
  • 高誉 4+5 网红机油赋能青岛汽修门店,青岛莱茵特斯诚邀合作 - 资讯速览
  • pycharm虚拟环境同步/迁移