🗣 Wd提问: MySQL源码事务实现
🤖 Ai回答: MySQL 的事务实现是一个复杂的系统工程,尤其在 InnoDB 存储引擎中(MySQL 默认事务型存储引擎),事务支持是其核心特性之一。下面我们将从 源码层面 深入剖析 MySQL(InnoDB)事务的实现机制。
一、事务的核心概念回顾
在深入源码前,先回顾事务的 ACID 特性:
Atomicity(原子性):事务要么全做,要么全不做。
Consistency(一致性):事务前后数据保持一致。
Isolation(隔离性):并发事务互不干扰。
Durability(持久性):事务提交后永久保存。
InnoDB 通过以下机制实现这些特性:
Undo Log → 原子性 & MVCC
Redo Log → 持久性
锁机制 + MVCC → 隔离性
两阶段提交(2PC) → 保证 redo/undo 与 binlog 一致性
二、InnoDB 事务模块源码结构概览
MySQL 源码目录结构(以 MySQL 8.0 为例):
storage/innobase/
├── trx/ ← 事务核心模块
│ ├── trx0trx.cc ← 事务对象管理
│ ├── trx0sys.cc ← 事务系统初始化
│ ├── trx0roll.cc ← 回滚操作
│ └── trx0purge.cc ← purge 线程清理 undo
├── log/ ← Redo 日志模块
├── buf/ ← Buffer Pool
├── lock/ ← 行锁、表锁
├── row/ ← 行操作(insert/update/delete)
└── include/ ← 头文件(如 trx0types.h, trx0trx.h)
三、事务生命周期源码分析
1、事务开始:`BEGIN` 或 `START TRANSACTION`
SQL 层调用 → 存储引擎层开启事务。
关键函数:
cpp
// sql/sql_parse.cc
mysql_execute_command() → 调用 trans_begin()
// storage/innobase/handler/ha_innodb.cc
ha_innobase::start_stmt() → innobase_trx_start()
最终调用:
cpp
// trx/trx0trx.cc
trx_t* trx_begin_for_mysql(trx_t* trx)
{
trx-id = trx_sys_get_new_trx_id(); // 分配事务 ID
trx-state = TRX_STATE_ACTIVE;
UT_LIST_ADD_LAST(trx_sys-rw_trx_list, trx); // 加入活跃事务链表
return trx;
}
✅ 事务对象 `trx_t` 是事务运行时的核心数据结构,包含事务 ID、状态、锁信息、undo 日志指针等。
2、事务执行:DML 操作(INSERT/UPDATE/DELETE)
以 `UPDATE` 为例:
cpp
// row/row0upd.cc
row_upd_step() →
btr_cur_update_in_place() →
trx_write_trx_id() // 写入当前事务 ID 到记录头
row_upd_rec_sys_fields() →
row_upd_rec_sys_field() →
trx_undo_report_row_operation() // 记录 undo log
关键点:
写 undo log:用于回滚和 MVCC 快照读。
加锁:根据隔离级别加行锁(如 X 锁)。
修改数据页:在 Buffer Pool 中修改,标记为 dirty。
3、事务提交:`COMMIT`
cpp
// trx/trx0trx.cc
trx_commit_for_mysql(trx_t* trx)
→ trx_commit(trx)
→ trx_prepare() // prepare 阶段(若涉及 binlog,则进入 2PC)
→ trx_commit_low(trx, mtr)
→ trx_write_serialisation_history(trx, mtr) // 写 undo log segment
→ trx_commit_in_memory(trx, mtr) // 内存中提交
→ trx-state = TRX_STATE_COMMITTED_IN_MEMORY
→ trx_release_locks(trx) // 释放行锁
→ trx_undo_assign_last_scan_rec() // 标记 undo 可被 purge
→ trx_flush_log_if_needed(lsn, trx) // 刷 redo log 到磁盘(根据 innodb_flush_log_at_trx_commit)
提交流程要点:
1、Prepare 阶段(仅当 `binlog` 启用且 `sync_binlog=1`):
写 redo log(prepare 状态)
写 binlog
2、Commit 阶段:
写 redo log(commit 状态)
根据 `innodb_flush_log_at_trx_commit` 决定是否刷盘
🔄 这就是经典的 两阶段提交(2PC),确保 binlog 和 redo log 一致性。
4、事务回滚:`ROLLBACK`
cpp
// trx/trx0roll.cc
trx_rollback_to_savepoint(trx, savept) 或 trx_rollback_all()
→ trx_roll_crash_recv_trx() →
row_undo_step() →
row_undo_ins() / row_undo_mod() // 根据 undo log 回滚插入或修改
→ trx_roll_cleanup(trx) // 清理事务资源
回滚依赖 undo log 中记录的旧值进行逆向操作。
四、事务隔离级别实现(MVCC + 锁)
InnoDB 通过 ReadView + Undo Log 实现 MVCC,支持四种隔离级别:
| 隔离级别 | 实现方式 |
| READ UNCOMMITTED | 直接读最新数据(无视未提交事务) |
| READ COMMITTED | 每次 SELECT 创建新 ReadView |
| REPEATABLE READ | 事务首次 SELECT 创建 ReadView 并复用 |
| SERIALIZABLE | 加锁读(Next-Key Lock) |
ReadView 源码:
cpp
// include/read0types.h
struct read_view_t {
trx_id_t low_limit_id; // 此 ID 的事务不可见
trx_id_t up_limit_id; // < 此 ID 的事务都可见
ulint n_trx_ids; // 活跃事务数组大小
trx_id_t* ids; // 活跃事务 ID 数组
trx_id_t creator_trx_id; // 创建该视图的事务 ID
};
在查询时:
cpp
// row/row0sel.cc
row_search_mvcc() →
lock_clust_rec_cons_read_sees() →
changes_visible(trx_id, view) → 判断记录是否对当前 ReadView 可见
五、Undo Log 与 Redo Log 协作
Undo Log:
存储在 undo tablespace 中(5.6+ 支持独立 undo 表空间)
用于:
回滚事务
构建历史版本(MVCC)
类型:
`TRX_UNDO_INSERT_REC` — 插入记录
`TRX_UNDO_UPD_DEL_REC` — 更新/删除记录
Redo Log:
WAL(Write-Ahead Logging)机制
保证事务持久性
在 `log/log0log.cc` 中实现刷盘逻辑
cpp
// log/log0log.cc
log_buffer_flush_to_disk() →
os_file_write() // 刷到磁盘
六、事务系统全局结构:`trx_sys_t`
在 `trx/trx0sys.cc` 中定义:
cpp
trx_sys_t* trx_sys;
struct trx_sys_t {
trx_id_t max_trx_id; // 下一个事务 ID
UT_LIST_BASE_NODE_T(trx_t) rw_trx_list; // 读写事务链表
UT_LIST_BASE_NODE_T(trx_t) mysql_trx_list; // 所有 MySQL 事务
rw_lock_t mutex; // 保护事务系统的读写锁
...
};
所有活跃事务都被维护在这个全局结构中。
七、Purge 线程清理 Undo
事务提交后,其 undo log 不会立即删除,而是由后台 purge 线程 异步清理:
cpp
// trx/trx0purge.cc
srv_purge_coordinator_thread() →
trx_purge() →
row_purge_step() →
row_purge_record_func() → 清理已提交事务的 undo 记录
八、关键数据结构总结
| 结构体 | 文件 | 作用 |
|
| `trx_t` | `trx0types.h` | 事务运行时上下文 |
| `read_view_t`| `read0types.h` | MVCC 快照视图 |
| `trx_sys_t` | `trx0sys.h`
📣 商家广告:





0
IP地址: 239.42.3.146
搜索次数: 4
提问时间: 2025-11-11 07:05:16
🛒 域名购买:
hangdang.net
mw.gs
02.gs
xm6.net
kou.red
tuosou.cn
gz.gold
43.gold
51.biz
3.bj.cn
❓️ 热门提问:
网站服务器放置地
dns日志
云计算包含
北京开发网站
怎么使用云主机
申请免费网页空间
韩国云主机vps
大数据物联网云计算之间的关系
mqtt服务器数据库
宝安网站建设
豌豆Ai站群搜索引擎系统
🌐 域名评估:
zf.gs
nn.he.cn
ll.tw.cn
catl.sn.cn
pz.com.hk
37.com.hk
znfd.cn
vzbw.cn
su8.live
q.ha.cn
⛏ 最新挖掘:
凯里酸汤鱼
贵阳烤脑花
都匀毛尖茶
花溪牛肉粉
贵阳烤生蚝
贵阳烤豆腐
贵阳纸包鱼
贵阳特色菜
🖌 热门作画:
🤝 关于我们:
豌豆Ai
域名
建站
站群
留痕
推广
评估
源码
开发Ai
工具
日记
价格
加盟
广告
流量
留言
联系
🗨 加入群聊:
🔗 友情链接:
贵阳电工维修电话
한국 검색엔진
ai提问
🧰 站长工具:
Ai工具 whois查询 搜索
📢 温馨提示:本站所有问答由Ai自动创作,内容仅供参考,若有误差请用“联系”里面信息通知我们人工修改或删除。
👉 技术支持:本站由豌豆Ai提供技术支持,使用的最新版:《豌豆Ai站群搜索引擎系统 V.25.10.25》搭建本站。