InnoDB 事务启动探秘:从 BEGIN 到第一个 SQL,MySQL 到底在忙什么?
InnoDB 事务启动探秘从 BEGIN 到第一个 SQLMySQL 到底在忙什么本文基于 MySQL 8.0.44 源码存储引擎为 InnoDB。目录为什么需要搞清楚 BEGIN 的行为BEGIN 语句的语法变体与解析器逻辑BEGIN 的执行入口trans_begin 函数辞旧隐式提交老事务与 MDL 锁释放迎新打上 OPTION_BEGIN 标记事务到底什么时候真正启动只读事务与读写事务的差异总结1. 为什么需要搞清楚 BEGIN 的行为在日常开发中BEGIN可能是我们最常写的 SQL 之一。在很多人的认知里BEGIN就是开启一个事务的意思——简单、直接、没什么好说的。但事实真的如此吗如果你曾经在同一个连接里连续执行过两次BEGIN可能会注意到一个现象第一次BEGIN之后做了一些数据修改还没提交第二次BEGIN一执行前面的修改就消失了。它们不是回滚了而是被自动提交了。这说明BEGIN干的活远比表面上看到的要多。要真正理解BEGIN的行为需要深入 MySQL 8.0.44 的源码看看从客户端敲下BEGIN到事务真正可用中间到底经历了什么。2. BEGIN 语句的语法变体与解析器逻辑MySQL 官方文档中开启事务的语法比想象中要丰富START TRANSACTION [transaction_characteristic [, transaction_characteristic] ...] transaction_characteristic: { WITH CONSISTENT SNAPSHOT | READ WRITE | READ ONLY } BEGIN [WORK]把这些语法要素排列组合可以得到以下 10 种 SQL 语句/* 1 */ BEGIN /* 2 */ BEGIN WORK /* 3 */ START TRANSACTION /* 4 */ START TRANSACTION READ WRITE /* 5 */ START TRANSACTION READ ONLY /* 6 */ START TRANSACTION WITH CONSISTENT SNAPSHOT /* 7 */ START TRANSACTION WITH CONSISTENT SNAPSHOT, READ WRITE /* 8 */ START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY /* 9 */ START TRANSACTION WITH CONSISTENT SNAPSHOT, READ WRITE, READ ONLY /* 10 */ START TRANSACTION READ WRITE, READ ONLY其中语句 1~8 可以正常执行语句 9 和 10 会报语法错误。为什么会报错翻一下语法解析器的代码就知道了。在sql/sql_yacc.yy中处理START TRANSACTION的逻辑是这样的start: START_SYM TRANSACTION_SYM opt_start_transaction_option_list { LEX *lex Lex; lex-sql_command SQLCOM_BEGIN; /* READ ONLY and READ WRITE are mutually exclusive. */ if (($3 MYSQL_START_TRANS_OPT_READ_WRITE) ($3 MYSQL_START_TRANS_OPT_READ_ONLY)) { YYTHD-syntax_error(); MYSQL_YYABORT; } lex-start_transaction_opt $3; } ;解析器的逻辑很直接**READ WRITE和READ ONLY是互斥的不能同时出现**。一旦检测到两者同时存在就主动报错。在可正常执行的语句中可以根据行为差异分为两类语句 1~5BEGIN、BEGIN WORK、START TRANSACTION、START TRANSACTION READ WRITE、START TRANSACTION READ ONLY这些语句不会立即启动事务也不会创建一致性读视图。事务的实际启动被延迟到真正需要的时候。语句 6~8带WITH CONSISTENT SNAPSHOT的三种形式这些语句会先启动事务然后立即创建一致性读视图。3. BEGIN 的执行入口trans_begin 函数在 MySQL 源码中所有显式开启事务的入口函数都是trans_begin。无论是BEGIN、BEGIN WORK还是START TRANSACTION最终都会汇聚到这个函数中。trans_begin函数的声明位于sql/transaction.cc中bool trans_begin(THD *thd, uint flags)这个函数有一句关键的注释直接点明了BEGIN语句的核心行为Beginning a transaction implicitly commits any current transaction and releases existing locks.翻译过来就是开始一个新事务会隐式提交当前事务并释放已有的锁。如果用四个字概括BEGIN语句在trans_begin中的核心工作那就是辞旧迎新——先提交老事务再准备新事务。4. 辞旧隐式提交老事务与 MDL 锁释放先来看一个常见场景你在 MySQL 客户端中执行了BEGIN开始了一个事务事务 1然后执行了一条INSERT语句。事务 1 还没有提交处于活跃状态此时你在同一个连接中又执行了一条BEGIN语句——事务 1 会怎样答案是事务 1 会被自动提交。原因很简单MySQL不支持嵌套事务。事务 1 还没结束又要开始事务 2事务 1 无处安放只能被隐式提交。BEGIN语句是如何判断当前连接中是否存在未提交事务的源码中的判断逻辑是这样的if (thd-in_multi_stmt_transaction_mode() || ...) { ... }而in_multi_stmt_transaction_mode()的实现是inline bool in_multi_stmt_transaction_mode() const { return variables.option_bits (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN); }检查当前线程的option_bits标志位中是否包含了OPTION_NOT_AUTOCOMMIT或OPTION_BEGIN。只要包含其中任意一个就说明当前连接中可能存在未提交的事务。如果检测到存在未提交事务BEGIN语句会主动调用提交操作res ha_commit_trans(thd, true);ha_commit_trans(thd, true)的第二个参数all传的是true表示这是一个隐式提交。这个提交不会记录在 binlog 里也不会触发commit相关的触发器只是悄无声息地把事务结束了。除了提交事务这个过程还会做一件重要的事释放 MDL 锁。MDLMetadata Lock是 Server 层用来保护表结构定义的锁机制。事务持有的 MDL 锁如果不释放后面的 DDL 语句比如ALTER TABLE就会被卡住。BEGIN隐式提交老事务时会一并把 MDL 锁释放掉。5. 迎新打上 OPTION_BEGIN 标记辞旧完成之后就该迎新了。MySQL 在资源使用上秉承一个原则能少分配就少分配能晚分配就晚分配。启动事务也需要分配资源因此BEGIN语句并不会真正启动一个事务只是做一些最轻量的准备工作。在trans_begin函数中这个准备工作主要包括以下几行代码thd-variables.option_bits | OPTION_BEGIN; thd-server_status | SERVER_STATUS_IN_TRANS; if (thd-tx_read_only) thd-server_status | SERVER_STATUS_IN_TRANS_READONLY;逐行来看**thd-variables.option_bits | OPTION_BEGIN**给当前连接的线程打上OPTION_BEGIN标记。这是最关键的一步。**thd-server_status | SERVER_STATUS_IN_TRANS**设置 Server 层状态表示当前连接处于事务中。**if (thd-tx_read_only) thd-server_status | SERVER_STATUS_IN_TRANS_READONLY**如果事务被标记为只读则额外设置只读事务状态位。那么OPTION_BEGIN这个标记到底起了什么作用在默认情况下MySQL 是自动提交autocommit1模式每执行完一条 SQL 语句就会自动提交。但一旦线程被打上OPTION_BEGIN标记自动提交行为就被禁用了。事务不会在每条 SQL 之后自动提交而是需要用户显式执行COMMIT或ROLLBACK才会结束事务。打个比方你去饭店点菜。BEGIN语句就相当于你跟服务员说我要开始点菜了服务员在你的桌号上贴了个用餐中的标签。但此时厨房并没有开始做菜——真正的做菜启动事务、分配事务 ID、生成 Read View 等要等你真正点了菜执行了具体的 SQL才会开始。贴标签这个动作几乎不花时间但它的意义在于告诉系统接下来的操作都属于同一个事务不要自动提交。6. 事务到底什么时候真正启动既然BEGIN语句不会真正启动事务那事务到底在什么时候启动答案是在执行BEGIN之后的第一条 SQL 语句时。当用户执行BEGIN之后线程只是被打上了OPTION_BEGIN标记事务对象trx_t的状态仍然是TRX_STATE_NOT_STARTED表示事务还未开始。在 InnoDB 的源码中事务状态定义在storage/innobase/include/trx0types.h中**TRX_STATE_NOT_STARTED**事务对象存在但尚未启动**TRX_STATE_ACTIVE**事务正在执行可以获取锁和修改数据直到执行第一条 SQL 语句不管是SELECT、UPDATE还是DELETEInnoDB 才会真正启动事务。这个启动过程由trx_start_if_not_started()函数触发。trx_start_if_not_started()内部会调用trx_start_low()完成以下关键操作将事务状态从TRX_STATE_NOT_STARTED修改为TRX_STATE_ACTIVE如果是读写事务分配真正的事务 IDtrx-id将事务对象加入全局事务链表此时事务才算是真正活了起来。我们在执行SHOW ENGINE INNODB STATUS时看到的ACTIVE状态就来源于此。这里还有一个值得注意的细节事务总是以读事务的身份启动的。即使你执行的是UPDATE语句事务在启动瞬间也是以读事务的身份出现事务 ID 被设置为 0。只有当事务确实需要写入数据时才会被分配一个真正的事务 ID。对于只读事务InnoDB 可以做一系列优化——不分配事务 ID、不注册到活跃事务链表、不分配 Undo 段。把启动事务和分配事务 ID解耦可以让只读事务以极低的成本运行。7. 只读事务与读写事务的差异在START TRANSACTION的语法中READ ONLY和READ WRITE选项会影响事务的行为。只读事务START TRANSACTION READ ONLY当以这种形式开启事务时thd-tx_read_only会被设置为true。当 Server 层接收到任何数据更改的 SQL 时都会直接拒绝请求不会进入引擎层。只读事务在 InnoDB 引擎层可以走优化过的逻辑相比读写事务开销更小不用分配事务 ID不用分配回滚段不用维护到全局事务链表读写事务链表中这些优化使得只读事务的成本极低非常适合只执行查询操作的场景。读写事务START TRANSACTION READ WRITE这是默认的事务模式。但如果当前实例的read_only打开了且当前连接不是超级账户则显式开启读写事务会报错。需要特别注意的是**BEGIN语句默认开启的是读写事务**。即使你后续只执行SELECT查询事务在启动时也是以读写事务的模式初始化的。不过如果 InnoDB 在真正执行查询时能判断出这是只读操作会进行相应的优化。8. 总结用一句话概括全文核心结论**BEGIN语句并不会马上启动一个新事务**。阶段操作事务状态关键代码执行BEGIN① 提交老事务如有② 释放 MDL 锁 ③ 打上OPTION_BEGIN标记 ④ 设置SERVER_STATUS_IN_TRANSTRX_STATE_NOT_STARTED未启动trans_begin()→ha_commit_trans()→ option_bits执行第一条 SQL① 调用trx_start_if_not_started()② 分配事务 ID读写事务③ 加入全局事务链表 ④ 状态变为TRX_STATE_ACTIVETRX_STATE_ACTIVE已启动trx_start_if_not_started()→trx_start_low()→state TRX_STATE_ACTIVEBEGIN语句的本质工作是辞旧迎新——提交可能存在的旧事务并释放其 MDL 锁然后给当前线程打上OPTION_BEGIN标记告诉 MySQL接下来的操作别自动提交。而事务的真正启动被延迟到了第一条 SQL 语句执行的那一刻。这种延迟启动的设计体现了 MySQL 一贯的资源管理哲学能不做的就不做能晚做的就晚做。对于只执行查询的短事务来说这种设计可以避免分配事务 ID、分配 Undo 段等不必要的开销从而提升系统的整体吞吐量。参考源码文件MySQL 8.0.44源码文件涉及的关键函数/结构sql/sql_yacc.yySTART TRANSACTION语法解析READ WRITE与READ ONLY互斥检查sql/transaction.cctrans_begin()、ha_commit_trans()sql/sql_class.hTHD结构体、in_multi_stmt_transaction_mode()、option_bits标志位定义storage/innobase/include/trx0types.htrx_state_t枚举定义TRX_STATE_NOT_STARTED、TRX_STATE_ACTIVE等storage/innobase/trx/trx0trx.cctrx_start_if_not_started()、trx_start_low()

相关新闻

Wand-Enhancer终极指南:5分钟解锁WeMod专业版所有功能

Wand-Enhancer终极指南:5分钟解锁WeMod专业版所有功能

Wand-Enhancer终极指南:5分钟解锁WeMod专业版所有功能 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 你是否厌倦了WeMod专业版的功能限…

2026/8/6 13:04:19 阅读更多 →
Java期末高效复习:从选择题入手构建核心知识体系与避坑指南

Java期末高效复习:从选择题入手构建核心知识体系与避坑指南

1. 项目概述:为什么选择题是Java期末复习的“定盘星”? 又到期末了,Java这门课是不是让你感觉知识点又多又杂,面对厚厚的教材和一堆实验代码,复习起来毫无头绪?很多同学一上来就抱着大题、编程题猛啃&#…

2026/8/6 13:03:19 阅读更多 →
如何免费解锁Grammarly高级功能:简单三步配置指南

如何免费解锁Grammarly高级功能:简单三步配置指南

如何免费解锁Grammarly高级功能:简单三步配置指南 【免费下载链接】autosearch-grammarly-premium-cookie 免费白嫖使用Grammarly Premium高级版 项目地址: https://gitcode.com/gh_mirrors/au/autosearch-grammarly-premium-cookie 想要体验Grammarly Premi…

2026/8/6 13:03:19 阅读更多 →

最新新闻

终极英雄联盟客户端自动化指南:三分钟告别繁琐登录

终极英雄联盟客户端自动化指南:三分钟告别繁琐登录

终极英雄联盟客户端自动化指南:三分钟告别繁琐登录 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否厌倦了每次玩英雄联盟时重…

2026/8/6 13:51:41 阅读更多 →
3个关键步骤解决BIThesis表格排版中的行间距问题

3个关键步骤解决BIThesis表格排版中的行间距问题

3个关键步骤解决BIThesis表格排版中的行间距问题 【免费下载链接】BIThesis 📖 北京理工大学非官方 LaTeX 模板集合,包含本科、研究生毕业设计模板及更多。🎉 (更多文档请访问 wiki 和 release 中的手册) 项目地址: …

2026/8/6 13:51:41 阅读更多 →
douyin-downloader:三步搞定抖音无水印批量下载

douyin-downloader:三步搞定抖音无水印批量下载

douyin-downloader:三步搞定抖音无水印批量下载 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…

2026/8/6 13:51:41 阅读更多 →
Cyber Engine Tweaks 终极指南:5个简单步骤解锁《赛博朋克2077》完整模组体验

Cyber Engine Tweaks 终极指南:5个简单步骤解锁《赛博朋克2077》完整模组体验

Cyber Engine Tweaks 终极指南:5个简单步骤解锁《赛博朋克2077》完整模组体验 【免费下载链接】CyberEngineTweaks Cyberpunk 2077 tweaks, hacks and scripting framework 项目地址: https://gitcode.com/gh_mirrors/cy/CyberEngineTweaks Cyber Engine Twe…

2026/8/6 13:51:41 阅读更多 →
还在手动整理视频重点做笔记?2026年适合学习者的5款视频总结助手实测对比

还在手动整理视频重点做笔记?2026年适合学习者的5款视频总结助手实测对比

简短结论 手动整理视频、录音重点做笔记效率极低,错漏多还耽误复习备考时间。本次实测对比5款主流视频总结助手,不同工具适配不同学生需求,听脑AI适合课堂记录、学术访谈整理等学生高频场景,可根据自身场景、预算选择对应工具。 本…

2026/8/6 13:51:41 阅读更多 →
UnityExplorer动态反射调试实用指南:运行时对象深度探索与修改

UnityExplorer动态反射调试实用指南:运行时对象深度探索与修改

UnityExplorer动态反射调试实用指南:运行时对象深度探索与修改 【免费下载链接】UnityExplorer An in-game UI for exploring, debugging and modifying IL2CPP and Mono Unity games. 项目地址: https://gitcode.com/gh_mirrors/un/UnityExplorer UnityExpl…

2026/8/6 13:50:40 阅读更多 →

日新闻

深入解析LimboAI C++内核:架构设计与性能优化实战

深入解析LimboAI C++内核:架构设计与性能优化实战

1. 项目概述:为什么我们需要深入LimboAI的C内核?如果你是一名使用Godot引擎的游戏开发者,尤其是对AI行为逻辑有较高要求的项目,那么LimboAI这个名字你大概率不会陌生。它作为Godot 4生态中一个备受瞩目的行为树与状态机插件&#…

2026/8/6 0:00:06 阅读更多 →
Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

1. 项目概述与核心思路大家好,我是老张,一个在游戏开发一线摸爬滚打了十多年的老码农。今天咱们接着聊《空洞骑士》风格2D动作游戏的Demo制作。上一期我们搭好了基础框架,处理了角色移动和碰撞,这一期,我们要让游戏世界…

2026/8/6 0:00:06 阅读更多 →
被动防火门市场前景发展趋势

被动防火门市场前景发展趋势

被动防火门依靠材质结构、密闭构造阻隔烟火蔓延,无需电控启动,是建筑被动消防系统核心构件,行业依托新规管控、城市更新、工业安全升级迎来稳定扩容,整体朝着合规化、专项化、低碳化、智能化方向发展。现阶段 GB12955‑2024 新版国…

2026/8/6 0:00:06 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/5 15:00:43 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/5 13:13:56 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/5 21:00:14 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →