A method, implemented by a replica node comprising a processing unit and memory that implements part of a database replication system, the replica node being in communication with a source node that stores at least one database table, the replica node storing a copy of the at least one database table, comprising:
- receiving, from a database client, a first query associated with a first database transaction;
- determining that the first query depends on a first database operation in the first database transaction;
- determining that the first database operation has not been executed by the replica node;
- by the replica node, delaying execution of the first query pending execution of the first database operation;
- by the replica node, determining that a time associated with the delaying execution exceeds a threshold;
- by the replica node, based on the determining that the time exceeds the threshold, forwarding the first query to the source node for execution by the source node;
- receiving the first database operation asynchronously from the source node;
- executing the first database operation at the replica node on the copy of the at least one database table;
- receiving a first synchronous notification from the source node to prepare to commit the first transaction;
- precommitting the first database transaction at the replica node, the precommitting marking the first database transaction as in-doubt at the replica node and assigning a first precommit ID value to the first database transaction, wherein an in-doubt database transaction is a database transaction that has not been committed or aborted and the first precommit ID value determines whether the first database transaction will be visible to a read operation;
- sending a first synchronous prepare commit acknowledgment to the source node, the first prepare commit acknowledgment indicating that the first database transaction was precommitted by the replica node;
- receiving, from the database client, a second query associated with a second database transaction;
- determining that the second query depends on a second database operation in the second database transaction;
- determining that the second database operation has not been executed by the replica node;
- based on the determining that the second database operation has not been executed by the replica node, holding the second query for execution by the replica node pending execution of the second database operation;
- receiving the second database operation asynchronously from the source node;
- executing the second database operation at the replica node on the copy of the at least one database table;
- in response to executing the second database operation at the replica node, executing the second query, wherein a delay associated with the holding does not exceed the threshold;
- receiving a second synchronous notification from the source node to prepare to commit the second database transaction;
- precommitting the second database transaction at the replica node, the precommitting marking the second database transaction as in-doubt at the replica node and assigning a second precommit ID value to the second database transaction, wherein an in-doubt database transaction is a database transaction that has not been committed or aborted and the second precommit ID value can be used to determine whether the second database transaction will be visible to a read operation;
- and
- sending a second synchronous prepare commit acknowledgment to the source node, the second prepare commit acknowledgment indicating that the second database transaction was precommitted by the replica node.