greenplum 中的事务回滚(rollback为例)

greenplum 回滚不是真回滚

greenplum 中不支持undo日志回滚,所以只是标记了新的事务号的状态,又后期的vacuum或scan自己去判断元组的可见性,并更新元组状态(SetHint)。

以rollback为例,看事务回滚过程

(1)master 清理

rollback 语句到达 master 走PortalRun->PortalRunMulti->PortalRunUtility->ProcessUtility->UserAbortTransactionBlock 逻辑,将当前事务状态转为 TBLOCK_ABORT_PENDING。 在结束事务 (finish_xact_command->CommitTransactionCommand) 的时候执行 AbortTransaction,将事务状态转为 TRANS_ABORT,开始master端的清理:

  1. 清理分发命令的状态
  2. 清理resource queue (即一个query所能使用的空间等,下面补充材料)
  3. 清理分区表的信息,看哪些分区表发生了改变
  4. 记录abort日志(改变了的database,表,已经提交的子事务),并唤醒 wal sender 进程(WalSndWakeup)去向 mirror 同步日志
  5. 标记本事务不在running
  6. 做一些cleanup(事务对应resourceOwner下的内存,将buffer解pin,表缓存条目),处理invalid的缓存消息(更新缓存)
  7. 回退分区表的信息
  8. 回退全局变量,on commit 动作,关闭 smgr。
  9. 更新统计信息
  10. 释放快照
  11. 清理一些与无效segment的连接(cdbcomponent_cleanupIdleQEs
(2)master 通知 segment 做清理

接着 master 端执行 rollbackDtxTransaction,将二阶段提交事务的状态从 DTX_STATE_ACTIVE_DISTRIBUTED 置为 DTX_STATE_NOTIFYING_ABORT_NO_PREPARED,然后发送 “Distributed Abort (No Prepared)” 的T(事务)类型的命令到segment(doNotifyingAbort)。

(3)segment 做清理

segment 走 exec_mpp_dtx_protocol_command逻辑,将 ps 显示更新为 在这里插入图片描述
执行abort命令(performDtxProtocolCommand->AbortOutOfAnyTransaction->AbortTransaction),清理和恢复一些现场(内存上下文与帐户,锁,信号接收),将当前事务状态转为 TRANS_ABORT,真正执行abort
1. 释放 portal
2. 清理共享快照的文件
3. 关闭大文件,清理大文件的 cookies,释放内存
4. 清理relationMap中改变的部分
5. 对于二阶段提交阶段发生的abort,要将二阶段提交锁释放(但不能删除,后面还会用)
6. 记录abort日志(改变了的database,表,已经提交的子事务),并唤醒 wal sender 进程(WalSndWakeup)去向 mirror 同步日志
7. 回退本地事务的 xid(EndLocalDistribXact
8. 标记本事务不在running
9. 做一些cleanup(事务对应resourceOwner下的内存,将buffer解pin,表缓存条目),处理invalid的缓存消息(更新缓存)
10.清理临时表 (smgrDoPendingDeletes),数据库,表空间
10. 回退全局变量,on commit 动作,关闭 smgr,清理临时文件。
11. 更新统计信息
12. 释放快照
13. 释放resourcegroup
14. 如果有错误信息,且是虚拟内存分配失败导致的(gp_memprot_kill)就

  1. 先断开所有自己的子节点连接(自己创建的gang内qe的连接,忽略其连接错误信息(RecycleGang),清理向segment的dispatch信息(cdbdisp_cleanupDispatcherHandle))
  2. 再断开所有的父节点连接(清理segment信息,并断开所有连接(cdbcomponent_destroyCdbComponents))

当前事务状态由 TBLOCK_PREPARE 转为 TBLOCK_DEFAULT 。此时不需要再通知master,而是直接通知客户端可以开始新的连接了。

补充材料:

ResourceQueue

使用:
可以设置一个resource queue 中活动 query 的最大上限,执行时内存大小,

  • create resource queue xxx with (active_statements=10, memory_limit=‘20 MB’, priority=‘MAX’, cost_overcommit=TRUE); --允许空闲时分配超过内存限制范围的内存
  • alter role mszjaas resource queue xxx;
  • set gp_resqueue_memory_policy=eager_free; --分阶段统计内存使用,而非统计整个过程的内存使用
  • set gp_resqueue_memory_policy=auto; --单条query允许超过内存

初始时所有用户使用 pg_default 队列,建议一个用户创建一个队列

查看命令

select * from gp_toolkit.gp_resq_activity;
select * from gp_toolkit.gp_resq_activity_by_queue;
select * from gp_toolkit.gp_resq_p riority_backend;
select * from gp_toolkit.gp_resq_priority_statement;
select * from gp_toolkit.gp_resq_role;
select * from gp_toolkit.gp_resqueue_status;

你可能感兴趣的:(postgresql)