接上文 pgpool-II的性能缺陷:
前文已經說到,pgpool-II在replication mode狀态下,是順次而非并行執行SQL文給各個DB節點。
從Source的角度,可以看到:
SimpleQuery → pool_send_and_wait → send_simplequery_message
/*
* Process Query('Q') message
* Query messages include an SQL string.
*/
POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend, int len, char *contents){
……
/* log query to log file if necessary */
if (pool_config->log_statement){
pool_log("statement: %s", contents);
}else{
pool_debug("statement2: %s", contents);
}
……
string = query_context->original_query;
if (!RAW_MODE){
……
/*
* Query is not commit/rollback
*/
if (!commit){
char *rewrite_query;
……
/*
* Optimization effort: If there's only one session, we do
* not need to wait for the master node's response, and
* could execute the query concurrently.
*/
if (pool_config->num_init_children == 1){
/* Send query to all DB nodes at once */
status = pool_send_and_wait(query_context, 0, 0);
/*
free_parser();
*/
return status;
}
/* Send the query to master node */
if (pool_send_and_wait(query_context, 1, MASTER_NODE_ID)
!= POOL_CONTINUE) {
free_parser();
return POOL_END;
}
}
/*
* Send the query to other than master node.
*/
if (pool_send_and_wait(query_context, -1, MASTER_NODE_ID)
!= POOL_CONTINUE{
free_parser();
return POOL_END;
}
……
}else{
……
}
return POOL_CONTINUE;
}
/*
* Send simple query and wait for response
* send_type:
* -1: do not send this node_id
* 0: send to all nodes
* >0: send to this node_id
*/
POOL_STATUS pool_send_and_wait(POOL_QUERY_CONTEXT *query_context,
int send_type, int node_id)
{
……
/* Send query */
for (i=0;i<NUM_BACKENDS;i++){
……
per_node_statement_log(backend, i, string);
if ( send_simplequery_message(CONNECTION(backend, i),
len, string, MAJOR(backend)) != POOL_CONTINUE) {
return POOL_END;
}
}
/* Wait for response */
……
if (wait_for_query_response(frontend, CONNECTION(backend, i),
MAJOR(backend)) != POOL_CONTINUE){
/* Cancel current transaction */
CancelPacket cancel_packet;
cancel_packet.protoVersion = htonl(PROTO_CANCEL);
cancel_packet.pid = MASTER_CONNECTION(backend)->pid;
cancel_packet.key= MASTER_CONNECTION(backend)->key;
cancel_request(&cancel_packet);
}
return POOL_CONTINUE;
}
/* Send query */ 一段,無阻塞方式向各節點發送SQL文。
/* Wait for response */ 一段,雖然也是個循環,但是是串行。
不過好在向各節點發SQL文的時候,幾乎是同時地發送指令,
是以 Wait for response 對一個節點檢查獲得SQL文執行結束消息以後,
幾乎同時也會獲得下一個節點SQL文執行結束的消息。
綜合以上:如果對一個節點單獨執行一段批處理耗時1小時,那麼在replication mode 多個節點運作條件下,執行時間将變成 2小時。
至于為何 pgpool-II把對 Master Node和 其他Node的執行分開,也許有特殊考慮,也許是為了保證Master Node的正确性。