博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
pgpool-II3.1 的begin transaction 和 自动追加 BEGIN/COMMIT问题
阅读量:6705 次
发布时间:2019-06-25

本文共 3208 字,大约阅读时间需要 10 分钟。

pgpool-II3.1 里面,有一些比较奇怪的做法,至少目前在我看来,是画蛇添足。

如果你没有声明 begin transaction 和 end/commit/rollback 。

当你执行一个SQL文的时候,如果事前没有 begin transaction 之类的,

它会在你所执行的单一的 update/insert/delete SQL 执行前,后,分别追加 BEGIN 和COMMIT。

虽然我认为这个追加是没有必要的,只要交给后台数据库就好了,但是还是先来探讨一下其实现机理。

具体是如何实现的呢。看代码:

start_internal_transaction 函数/* * Start an internal transaction if necessary.  */ POOL_STATUS start_internal_transaction(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, Node *node){   int i;   /* If we are not in a transaction block,    * start a new transaction   */  if (is_internal_transaction_needed(node)){     for (i=0;i
pid, MASTER_CONNECTION(backend)->key, 0) != POOL_CONTINUE) return POOL_END; /* Mark that we started new transaction */ INTERNAL_TRANSACTION_STARTED(backend, i) = true; pool_unset_writing_transaction(); } } } return POOL_CONTINUE; } end_internal_transaction 函数 /* * End internal transaction. */ POOL_STATUS end_internal_transaction(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { …… /* We need to commit from secondary to master. */ for (i=0;i
pid,MASTER_CONNECTION(backend)->key, 1) != POOL_CONTINUE) { INTERNAL_TRANSACTION_STARTED(backend, i) = false; POOL_SETMASK(&oldmask); return POOL_END; } INTERNAL_TRANSACTION_STARTED(backend, i) = false; } } /* Commit on master */ if (TSTATE(backend, MASTER_NODE_ID) != 'I' && INTERNAL_TRANSACTION_STARTED(backend, MASTER_NODE_ID)) { …… per_node_statement_log(backend, MASTER_NODE_ID, "COMMIT"); if (do_command(frontend, MASTER(backend), "COMMIT", MAJOR(backend), MASTER_CONNECTION(backend)->pid,MASTER_CONNECTION(backend)->key, 1) != POOL_CONTINUE) { INTERNAL_TRANSACTION_STARTED(backend, MASTER_NODE_ID) = false; POOL_SETMASK(&oldmask); return POOL_END; } INTERNAL_TRANSACTION_STARTED(backend, MASTER_NODE_ID) = false; } POOL_SETMASK(&oldmask); return POOL_CONTINUE; }

其中所使用的 is_internal_transaction_needed 函数,其篇幅比较长,代码省略。

其主要做法,就是把 delete/insert/update 之类的关键字放到一个list中,然后用二分法查找。
如果命中,就认为 internal_transaction_needded。

从更高的层次看,有如下的调用关系:

pool_process_query  →  ProcessFrontEndResponse  和 ProcessBackendResponse

ProcessFrontEndResponse → 

      SimpleQuery → start_internal_transaction  → is_internal_transaction_needed

ProcessBackendResponse → 

      ReadyForQuery →end_internal_transaction

需要注意,在 start_internal_transaction 中追加 BEGIN需要以下几个条件:

       i)  Interal transaction 被认定是必须的 

   ii) INTERNAL_TRANSACTION_STARTED 标志位被置位

       iii) 各DB节点的TSTATE 状态是初始状态 I

而在 end_internal_transaction 中追加 COMMIT需要以下几个条件:

     i) Interal transaction 被认定是必须的

       ii) INTERNAl_TRANSACTION_STARTED标志位被置位

       iii) 各DB节点的TSTATE 状态时初始状态 I

普通的单一SQL文执行的时候,上述的条件均可得到满足。

但是,像begein transaction 这样的语句,一旦执行,会改变DB节点的 TSTATE状态为 T。

这样,即使后面再有 单一SQL文被执行,也没有可能满足上面的条件了。

直到遇到了 begin-transaction--commit/rollback  的 commit/rollback , TSTATE状态恢复为I 。

 

换句话说,其实pgpool-II中,根本就没有对 begin transaction 语句的识别部分的代码!诡异!

转载地址:http://mwflo.baihongyu.com/

你可能感兴趣的文章
读书笔记: CLR篇 (让你了解C#.Net的实质) (20111219更新)
查看>>
Red Hat Enterprise Linux 各版本详细说明
查看>>
解决matplotlib库在PyCharm和命令行都无法正常显示问题
查看>>
(一)Linux实操之——权限、任务调度、磁盘分区
查看>>
浅谈javascript中的作用域
查看>>
HDOJ---2577 How to Type[DP(两个DP数组)]
查看>>
Java性能总结三(转)
查看>>
Cocos2d-x for Windows Phone 8 发布
查看>>
Delphi多媒体设计之TMediaPlayer组件(七)
查看>>
生产者消费者问题理解与Java实现
查看>>
python之排序操作及heapq模块
查看>>
《设计模式》2.创建型模式
查看>>
针对于iosAPP内嵌H5,-webit-overflow-scrolling:touch;产生空白情况
查看>>
深入浅出JavaScript运行机制
查看>>
LeetCode 272 Closest Binary Tree Traversal II 解题思路
查看>>
video自动播放 隐藏播放控制条,并且用点击 video 元素的时候 控制暂停和播放...
查看>>
代码重构之消除分支结构
查看>>
ingress controller学习记录
查看>>
328. Odd Even Linked List
查看>>
分布式应急响应
查看>>