);
}
+ /**
+ * @return string|null
+ */
+ final protected function getTransactionRoundId() {
+ // If transaction round participation is enabled, see if one is active
+ if ( $this->getFlag( self::DBO_TRX ) ) {
+ $id = $this->getLBInfo( 'trxRoundId' );
+
+ return is_string( $id ) ? $id : null;
+ }
+
+ return null;
+ }
+
public function pendingWriteQueryDuration( $type = self::ESTIMATE_TOTAL ) {
if ( !$this->trxLevel ) {
return false;
# In the first case, the only options going forward are (a) ROLLBACK, or
# (b) ROLLBACK TO SAVEPOINT (if one was set). If the later case, the only
# option is ROLLBACK, since the snapshots would have been released.
- if ( is_object( $tempIgnore ) ) {
- // Ugly hack to know that savepoints are in use for postgres
- // FIXME: remove this and make DatabasePostgres use ATOMIC_CANCELABLE
- } else {
- $this->trxStatus = self::STATUS_TRX_ERROR;
- $this->trxStatusCause =
- $this->makeQueryException( $lastError, $lastErrno, $sql, $fname );
- $tempIgnore = false; // cannot recover
- }
+ $this->trxStatus = self::STATUS_TRX_ERROR;
+ $this->trxStatusCause =
+ $this->makeQueryException( $lastError, $lastErrno, $sql, $fname );
+ $tempIgnore = false; // cannot recover
} else {
# Nothing prior was there to lose from the transaction
$this->trxStatus = self::STATUS_TRX_OK;
private function handleSessionLoss() {
// Clean up tracking of session-level things...
// https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
- // https://www.postgresql.org/docs/9.1/static/sql-createtable.html (ignoring ON COMMIT)
+ // https://www.postgresql.org/docs/9.2/static/sql-createtable.html (ignoring ON COMMIT)
$this->sessionTempTables = [];
// https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock
// https://www.postgresql.org/docs/9.4/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
}
final public function onTransactionIdle( callable $callback, $fname = __METHOD__ ) {
+ if ( !$this->trxLevel && $this->getTransactionRoundId() ) {
+ // Start an implicit transaction similar to how query() does
+ $this->begin( __METHOD__, self::TRANSACTION_INTERNAL );
+ $this->trxAutomatic = true;
+ }
+
$this->trxIdleCallbacks[] = [ $callback, $fname ];
if ( !$this->trxLevel ) {
$this->runOnTransactionIdleCallbacks( self::TRIGGER_IDLE );
}
final public function onTransactionPreCommitOrIdle( callable $callback, $fname = __METHOD__ ) {
- if ( $this->trxLevel || $this->getFlag( self::DBO_TRX ) ) {
- // As long as DBO_TRX is set, writes will accumulate until the load balancer issues
- // an implicit commit of all peer databases. This is true even if a transaction has
- // not yet been triggered by writes; make sure $callback runs *after* any such writes.
+ if ( !$this->trxLevel && $this->getTransactionRoundId() ) {
+ // Start an implicit transaction similar to how query() does
+ $this->begin( __METHOD__, self::TRANSACTION_INTERNAL );
+ $this->trxAutomatic = true;
+ }
+
+ if ( $this->trxLevel ) {
$this->trxPreCommitCallbacks[] = [ $callback, $fname ];
} else {
// No transaction is active nor will start implicitly, so make one for this callback
$this->trxWriteCallers = [];
// First SELECT after BEGIN will establish the snapshot in REPEATABLE-READ.
// Get an estimate of the replication lag before any such queries.
+ $this->trxReplicaLag = null; // clear cached value first
$this->trxReplicaLag = $this->getApproximateLagStatus()['lag'];
// T147697: make explicitTrxActive() return true until begin() finishes. This way, no
// caller will think its OK to muck around with the transaction just because startAtomic()
}
public function getSessionLagStatus() {
- return $this->getTransactionLagStatus() ?: $this->getApproximateLagStatus();
+ return $this->getRecordedTransactionLagStatus() ?: $this->getApproximateLagStatus();
}
/**
* is this lag plus transaction duration. If they don't, it is still
* safe to be pessimistic. This returns null if there is no transaction.
*
+ * This returns null if the lag status for this transaction was not yet recorded.
+ *
* @return array|null ('lag': seconds or false on error, 'since': UNIX timestamp of BEGIN)
* @since 1.27
*/
- final protected function getTransactionLagStatus() {
- return $this->trxLevel
+ final protected function getRecordedTransactionLagStatus() {
+ return ( $this->trxLevel && $this->trxReplicaLag !== null )
? [ 'lag' => $this->trxReplicaLag, 'since' => $this->trxTimestamp() ]
: null;
}