OpenGauss MOT表实现代码走读
一. 前言MOT表是openGauss中一个重要的亮点特性其得益于本地内存和全局内存的设计实现了无锁操作Mass索引和commit的时候才统一做checkpoint等能力实现了高并发读写。本文主要走读openGauss中的代码了解其如何实现的。二. MOT表读流程代码走读读流程的核心是如何从mass索引中读取元组的数据其入口为MOTIterateForeignScan核心流程为MOTIterateForeignScan do { if (!festate-m_cursorOpened) { MOTAdaptor::OpenCursor // 初始化索引扫描信息 if (festate-m_bestIx nullptr || festate-m_bestIx-m_fullScan) { // 无索引的场景 MOT::Index* ix festate-m_table-GetPrimaryIndex() // 使用MOT表的伪索引 } festate-m_cursor[i] festate-m_bestIx-m_ix-Search // 到masstree中查找满足扫描键的迭代器 const_castIndexImpl(m_index).iteratorScan(keybuf, keylen, matchKey....) } MOT::Sentinel* sentinel festate-m_cursor[0]-GetPrimarySentinel(); // 获取到版本 currRow festate-m_currTxn-RowLookup(festate-m_internalCmdOper, sentinel, rc); // 获取当前可见的一行数据 TxnManager::RowLookup RC res AccessLookup(type, originalSentinel, local_row); // 查找本地内存 switch (res) { case RC::RC_LOCAL_ROW_NOT_FOUND: // 本地内存找不到 local_row m_accessMgr-GetVisibleRowVersion(originalSentinel, GetVisibleCSN()); // 查找全局内存 } MOTAdaptor::UnpackRow // MOT数据转成普通元组数据 festate-m_cursor[0]-Next(); // 游标下移 }三. MOT表写流程代码走读MOT的写流程核心为如何写本地内存以及如何提交到全局内存如下为核心流程MOTExecForeignInsert MOTAdaptor::InsertRow MOT::RC MOTAdaptor::InsertRow PackRow(slot, table, fdwState-m_attrsUsed, newRowData) // 转成MOT的行格式 table-InsertRow(row, fdwState-m_currTxn) // 插入行 insItem-SetItem(row, ix); // 创建插入项 txn-InsertRow(row); // 私有内存插入数据 MOT::TxnManager::InsertRow m_accessMgr-GetInsertMgr()-ExecuteOptimisticInsert(row, updateColumnKey) while (currentItem ! EndCursor()) { currentItem-m_index-BuildKey(table, row, tKey); reinterpret_castMOT::Index*(currentItem-m_index)-IndexInsert // 插入索引 TxnInsertAction::AddInsertToLocalAccess // 插入到本地内存 MOT::TxnAccess::AddInsertToLocalAccess curr_access-m_origSentinel org_sentinel // 设置哨兵 m_rowsSet-insert // 插入本地内存 }本地内存提交到全局内存只有在commit的时候才会触发MOT::TxnManager::RecordCommit CommitInternal m_occManager.WriteChanges MOT::OccTransactionManager::WriteChanges GetCheckpointManager()-ApplyWrite(txMan, access-GetRowFromHeader(), access) CheckpointManager::ApplyWrite s-SetStableStatus(!m_availableBit) // 告诉checkpoint服务数据需要持久化 access-WriteGlobalChanges MOT::Access::WriteGlobalChanges GetLocalInsertRow()-SetCommitSequenceNumber(csn) // 设置csn GetLocalInsertRow()-SetTable(GetLocalInsertRow()-GetOrigTable()) // 往全局表推送变化四. 创建MOT表代码走读创建MOT表的核心为如何创建mass索引的伪列其核心流程为MOT::RC MOTAdaptor::CreateTable table-Init // 表初始化 AddTableColumns(table, stmt-base.tableElts, hasBlob) // 为表增加列 primaryIdx MOT::IndexFactory::CreatePrimaryIndexEx(...DEFAULT_TREE_FLAVOR...) primaryIdx-SetLenghtKeyFields(0, -1, 8); primaryIdx-SetFakePrimary(true); res txn-CreateIndex(table, primaryIdx, true); // 默认创建一个伪主键索列作为索引如何指定了表的主键索引那么MOT表创建索引的时候会将伪列索引删除保证只有1个主键索引MOTAdaptor::CreateIndex MOT::Table::UpdatePrimaryIndex if (this-m_primaryIndex) { DeleteIndex(this-m_primaryIndex); // 删除伪主键索引 } SetPrimaryIndex(index); // 用表的主键索引替换表的伪主键索引