一. 前言
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_cast<IndexImpl&>(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_cast<MOT::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); // 用表的主键索引替换表的伪主键索引