H2 Database 事务 Commit 流程实现原理使用测试 Demo: 123begin;insert into test values(1);commit; 功能模块类总体流程1234567891011121314解析 commit 语句执行 commit 语句 设置事务状态为已提交 根据 undoLogId 判断事务是否有更改操作,有更改继续提交 CAS 设置当前事务状态为已提交到 committingTransactions 遍历 undoLog mvMap 追加标记 undoLog 已提交到 undoLog mvMap 上 获取当前 undoLog 操作涉及的 mvMap id 遍历到对应 Page 的对应 index 将 VersionedValueUncommitted 类型更新成 DefaultRow 类型事务清理操作 清理 undoLog mvMap(更新 root 节点为 empty) 清理事务状态 释放 table 锁 代码流程1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980org.h2.command.dml.TransactionCommand#update org.h2.engine.SessionLocal#commit org.h2.mvstore.tx.Transaction#commit 提交事务 org.h2.mvstore.tx.Transaction#markTransactionEnd 标记事务结束 org.h2.mvstore.tx.Transaction#setStatus 2.设置事务状态为已提交 1.获取当前 state & logId org.h2.mvstore.tx.Transaction#getLogId 获取当前 undo log id org.h2.mvstore.tx.Transaction#getStatus 1.获取当前状态 2.判断当前状态允许变更为目标状态,然后变更为目标状态,此处设置为STATUS_COMMITTED状态 org.h2.mvstore.tx.Transaction#composeState 创建新状态(transaction status + undo log id) 原子变更状态 org.h2.mvstore.tx.Transaction#hasChanges 3.判断是否有更改(undo log id 不为0) org.h2.mvstore.tx.TransactionStore#commit 4.如果有更改,执行提交操作 获取当前事务对应的 undo log mvMap org.h2.mvstore.MVMap#cursor 获取 undo log mvMap 的 cursor org.h2.mvstore.tx.TransactionStore#markUndoLogAsCommitted 1.2.标记 undo log 已提交 org.h2.mvstore.tx.TransactionStore#addUndoLogRecord 追加标记 undo log 为 committed(不会修改之前的) org.h2.mvstore.tx.TransactionStore#getOperationId 2.计算得到 undo log key(transaction id + undo log id) org.h2.mvstore.MVMap#append 3.追加 undo log mvMap(将 key:undoLogKey, value:undoLogRecord 添加到 map 里) org.h2.mvstore.MVMap#getRoot 获取根节点 org.h2.mvstore.MVMap#lockRoot 1.锁定根节点 org.h2.mvstore.RootReference#getAppendCounter 2.获取当前写入下标 4.key 写入 buffer 5.value 写入 buffer 如果 buffer 超出阈值,则先将未保存到 btree 页面上的 buffer 数据保存到 btree 上 org.h2.mvstore.MVMap#unlockRoot 4.解锁 root org.h2.mvstore.tx.TransactionStore#flipCommittingTransactionsBit 2.标记事务更改为“已提交”的原子操作(cas 设置当前事务状态为已提交到 committingTransactions) org.h2.mvstore.Cursor#next 3.遍历当前事务对应的 undoLog mvMap 里的所有 undo log key org.h2.mvstore.Cursor#getValue 获取 undo log key 和 undo log record 获取 undo log 操作涉及的 map id org.h2.mvstore.tx.TransactionStore#openMap 5.打开 mvMap(当前事务的当前 undo log 操作对应的行数据map) 获取当前 undo log 操作的 key(比如行主键id) org.h2.mvstore.tx.CommitDecisionMaker#setUndoKey org.h2.mvstore.MVMap#operate 根据 undo key 操作 map org.h2.mvstore.MVMap#flushAndGetRoot 1.获取 mvMap 根节点 org.h2.mvstore.CursorPos#traverseDown 2.从根节点开始,根据 key 遍历 tree,找到 key 的位置 pos 3.获取操作(插入/删除..)位置对应的 pos 对应的 page 获取当前 key 对应的在 page 上的下标 org.h2.mvstore.Page.Leaf#getValue 4.根据索引获取 page 上的值,如果是插入操作此处为 null,因为原来没有值 org.h2.mvstore.MVMap.DecisionMaker#decide 5.根据 当前值、目标值 和 游标位置 决定操作类型 org.h2.mvstore.tx.CommitDecisionMaker#selectValue 获取当前值(如果是事务commit操作,此处会获取 VersionedValueUncommitted 里的 defaultRow) org.h2.mvstore.Page#copy 复制当前page org.h2.mvstore.Page.Leaf#setValue 设置值(更新成DefaultRow) org.h2.mvstore.RootReference#updateRootPage 更新 root page org.h2.mvstore.MVMap#clear 清理 undo log mvMap(更新 root 为 empty.可以 debug 查看进入这个方法前后 undoLog 对象的变化) org.h2.mvstore.tx.TransactionStore#endTransaction 结束事务-清理事务状态 org.h2.engine.SessionLocal#endTransaction 结束事务-释放table锁