pgpool2.git / summary / log / commit / refs

commit    1e69f54c33d00b474d2577eeaaf166cc8970ecf6
Author:   Yoshiyuki Asaba <y-asaba at pgfoundry.org>
Date:     Thu Mar 13 13:11:13 2008 +0000

    * Fixed kind mismatch error in master slave mode with following
      scenario. This bug was introduced in pgpool-II v2.0.
    
      BEGIN;
      SET client_encoding TO SJIS;
    
    * Fixed load balancing in master slave mode. This bug was introduced
      in pgpool-II v2.0.


pool_process_query.c | 103 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 31 deletions(-) diff --git a/pool_process_query.c b/pool_process_query.c index 74f8afbd3..724f167e7 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -197,6 +197,9 @@ static Portal *unnamed_statement = NULL; static Portal *unnamed_portal = NULL; static int select_in_transaction = 0; /* non 0 if select query is in transaction */ +/* non 0 if "BEGIN" query with extended query protocol received */ +static int receive_extended_begin = 0; + static PreparedStatementList prepared_list; /* prepared statement name list */ static int is_drop_database(Node *node); /* returns non 0 if this is a DROP DATABASE command */ @@ -1071,7 +1074,7 @@ static POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend, /* * PREPARE, DEALLOCATE and SET statements must be replicated. */ - if (MASTER_SLAVE) + if (MASTER_SLAVE && TSTATE(backend) != 'E') force_replication = 1; if (frontend) @@ -1369,6 +1372,17 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend, pool_debug("Execute: portal name <%s>", string); + if (receive_extended_begin) + { + /* send sync message */ + send_extended_protocol_message(backend, MASTER_NODE_ID, "S", 0, ""); + + kind = pool_read_kind(backend); + if (kind != 'Z') + return POOL_END; + if (ReadyForQuery(frontend, backend, 0) != POOL_CONTINUE) + return POOL_END; + } portal = lookup_prepared_statement_by_portal(&prepared_list, string); @@ -1383,11 +1397,28 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend, string1 = portal->sql_string; node = (Node *)p_stmt->query; - if ((IsA(node, PrepareStmt) || IsA(node, DeallocateStmt) || IsA(node, VariableSetStmt)) && - MASTER_SLAVE) + if ((IsA(node, PrepareStmt) || IsA(node, DeallocateStmt) || + IsA(node, VariableSetStmt)) && + MASTER_SLAVE && TSTATE(backend) != 'E') { force_replication = 1; } + /* + * JDBC driver sends "BEGIN" query internally if setAutoCommit(false). + * But it does not send Sync message after "BEGIN" query. + * In extended query protocol, PostgreSQL returns + * ReadyForQuery when a client sends Sync message. + * We can't know a transaction state... + * So pgpool send Sync message internally. + */ + else if (IsA(node, TransactionStmt) && MASTER_SLAVE) + { + TransactionStmt *stmt = (TransactionStmt *) node; + + if (stmt->kind == TRANS_STMT_BEGIN || + stmt->kind == TRANS_STMT_START) + receive_extended_begin = true; + } if (load_balance_enabled(backend, node, string1)) start_load_balance(backend); @@ -1409,10 +1440,10 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend, return POOL_END; } */ - commit = is_commit_query((Node *)p_stmt->query); } - else if (MASTER_SLAVE) + + if (MASTER_SLAVE) { master_slave_was_enabled = 1; MASTER_SLAVE = 0; @@ -1515,23 +1546,6 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend, if (status != POOL_CONTINUE) return status; - /* end load balance mode */ - if (in_load_balance) - end_load_balance(backend); - - if (master_slave_dml) - { - MASTER_SLAVE = 1; - master_slave_was_enabled = 0; - master_slave_dml = 0; - if (force_replication) - { - REPLICATION = 0; - replication_was_enabled = 0; - force_replication = 0; - } - } - return POOL_CONTINUE; } @@ -1908,9 +1922,35 @@ static POOL_STATUS ReadyForQuery(POOL_CONNECTION *frontend, pool_debug("ReadyForQuery: message length: %d", len); - state = pool_read_kind(backend); - if (state < 0) - return POOL_END; + /* + * Do not check transaction state in master/slave mode. + * Because SET, PREPARE, DEALLOCATE are replicated. + * If these queries are executed inside a transaction block, + * transation state is inconsistency. But it is no problem. + */ + if (master_slave_dml) + { + char kind, kind1; + + if (pool_read(MASTER(backend), &kind, sizeof(kind))) + return POOL_END; + + for (i = 0; i < NUM_BACKENDS; i++) + { + if (!VALID_BACKEND(i) || IS_MASTER_NODE_ID(i)) + continue; + + if (pool_read(CONNECTION(backend, i), &kind1, sizeof(kind))) + return POOL_END; + } + state = kind; + } + else + { + state = pool_read_kind(backend); + if (state < 0) + return POOL_END; + } /* set transaction state */ pool_debug("ReadyForQuery: transaction state: %c", state); @@ -2958,11 +2998,6 @@ static POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend, status = SimpleQuery(frontend, backend, NULL); break; -/* - case 'S': - status = Sync(frontend, backend); - break; -*/ case 'E': /* Execute message */ status = Execute(frontend, backend); break; @@ -2971,10 +3006,15 @@ static POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend, status = Parse(frontend, backend); break; + case 'S': + receive_extended_begin = 0; + /* fall through */ + default: if (MAJOR(backend) == PROTO_MAJOR_V3) { - if (MASTER_SLAVE) + if (MASTER_SLAVE && + (TSTATE(backend) != 'I' || receive_extended_begin)) { pool_debug("kind: %c master_slave_dml enabled", fkind); master_slave_was_enabled = 1; @@ -4134,6 +4174,7 @@ static int reset_backend(POOL_CONNECTION_POOL *backend, int qcnt) internal_transaction_started = 0; mismatch_ntuples = 0; select_in_transaction = 0; + receive_extended_begin = 0; qn = pool_config->num_reset_queries; [parent: 9794570f81a5]