openGauss之alter table实现流程代码走读
本文分析了openGauss中ALTER TABLE操作的实现流程。其核心是通过创建临时表、逐行转换数据并交换表文件的方式完成表结构变更。具体步骤包括:1)通过ProcessUtilitySlow入口获取表锁;2)根据ALTER类型封装命令;3)创建临时新表并加锁;4)扫描旧表数据,对需要修改的列进行表达式计算;5)将转换后的数据插入临时表;6)最后通过swap_relation_files交换新
·
一. 前言
openGauss的alter table操作大体的实现思路为“新建临时表 -> 读取旧表的数据 -> 旧表的数据逐行进行变更计算 -> 变更完后insert到临时表 -> 临时表和变更前的表进行数据文件交换”。 本文走读openGauss的代码了解openGauss中如何实现上述流程的。
二. alter table代码走读
alter table等DDL操作的入口均为ProcessUtilitySlow,如下的代码走读的核心调用流程:
ProcessUtilitySlow
lockmode = AlterTableGetLockLevel(atstmt->cmds);
LOCKMODE lockmode = AccessExclusiveLock; // 默认8级锁
GetPartitionLockLevel
if (PARTITION_DDL_CMD(subType)) {
return ShareUpdateExclusiveLock; // 分区操作为4级锁
} else {
return AccessExclusiveLock; // 其他操作为8级锁
}
rel_id = AlterTableLookupRelation(atstmt, lockmode); // 原表加8级锁
stmts = transformAlterTableStmt(rel_id, atstmt, query_string);
switch (cmd->subtype) {
....
case AT_AlterColumnType: // 根据alter类型封装成cmd
....
}
AlterTable(rel_id, lockmode, (AlterTableStmt*)stmt);
ATController
ATPrepCmd(&wqueue, rel, cmd, recurse, false, lockmode); // cmd封装成NewColumnValue
transform = (Node*)expression_planner((Expr*)transform); // 类型转换转成expr
newval->expr = (Expr*)transform
ATRewriteTables
ExecRewriteRowTable
Oid OIDNewHeap = make_new_heap(tab->relid, NewTableSpace, oldRelLockMode); // 根据旧表的元数据新建一个临时新表
Relation newRel = heap_open(OIDNewHeap, lockmode); // 新表加临时锁
ATRewriteTable
ATRewriteTableInternal
// 逐行读取旧表数据
while ((tuple = (HeapTuple) tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) {
tableam_tops_deform_tuple(tuple, oldTupDesc, values, isnull); // 读取旧的数据
// 对于需要重新计算列数据的列进行重新计算,重新计算后的值放在values[x]中
foreach (l, tab->newvals) {
// 重新计算列修改后的数据
NewColumnValue *ex = (NewColumnValue*)lfirst(l);
values[ex->attnum - 1] = ExecEvalExpr(ex->exprstate, econtext, &isnull[ex->attnum - 1]);
// 新的数据写入新的临时表
tableam_tuple_insert(newrel, tuple, mycid, hi_options, bistate);
}
}
finish_heap_swap // 所有的行完成转换后,将旧表的数据和新临时表的数据做交换
swap_relation_files // 交换新旧表的文件实现数据交换更多推荐
所有评论(0)