$e = null; // first exception
$this->forEachOpenMasterConnection( function ( Database $conn ) use ( $type, &$e ) {
$conn->setTrxEndCallbackSuppression( false );
- if ( $conn->writesOrCallbacksPending() ) {
- // This happens if onTransactionIdle() callbacks leave callbacks on *another* DB
- // (which finished its callbacks already). Warn and recover in this case. Let the
- // callbacks run in the final commitMasterChanges() in LBFactory::shutdown().
- $this->queryLogger->info( __METHOD__ . ": found writes/callbacks pending." );
+ // Callbacks run in AUTO-COMMIT mode, so make sure no transactions are pending...
+ if ( $conn->writesPending() ) {
+ // This happens if onTransactionIdle() callbacks write to *other* handles
+ // (which already finished their callbacks). Let any callbacks run in the final
+ // commitMasterChanges() in LBFactory::shutdown(), when the transaction is gone.
+ $this->queryLogger->warning( __METHOD__ . ": found writes pending." );
return;
} elseif ( $conn->trxLevel() ) {
// This happens for single-DB setups where DB_REPLICA uses the master DB,
$this->trxRoundId = false;
$this->forEachOpenMasterConnection(
function ( IDatabase $conn ) use ( $fname, $restore ) {
- if ( $conn->writesOrCallbacksPending() || $conn->explicitTrxActive() ) {
- $conn->rollback( $fname, $conn::FLUSHING_ALL_PEERS );
- }
+ $conn->rollback( $fname, $conn::FLUSHING_ALL_PEERS );
if ( $restore ) {
$this->undoTransactionRoundFlags( $conn );
}
}
/**
+ * Make all DB servers with DBO_DEFAULT/DBO_TRX set join the transaction round
+ *
+ * Some servers may have neither flag enabled, meaning that they opt out of such
+ * transaction rounds and remain in auto-commit mode. Such behavior might be desired
+ * when a DB server is used for something like simple key/value storage.
+ *
* @param IDatabase $conn
*/
private function applyTransactionRoundFlags( IDatabase $conn ) {
// DBO_TRX is controlled entirely by CLI mode presence with DBO_DEFAULT.
// Force DBO_TRX even in CLI mode since a commit round is expected soon.
$conn->setFlag( $conn::DBO_TRX, $conn::REMEMBER_PRIOR );
- // If config has explicitly requested DBO_TRX be either on or off by not
- // setting DBO_DEFAULT, then respect that. Forcing no transactions is useful
- // for things like blob stores (ExternalStore) which want auto-commit mode.
+ }
+
+ if ( $conn->getFlag( $conn::DBO_TRX ) ) {
+ $conn->setLBInfo( 'trxRoundId', $this->trxRoundId );
}
}
return; // transaction rounds do not apply to these connections
}
+ if ( $conn->getFlag( $conn::DBO_TRX ) ) {
+ $conn->setLBInfo( 'trxRoundId', false );
+ }
+
if ( $conn->getFlag( $conn::DBO_DEFAULT ) ) {
$conn->restoreFlags( $conn::RESTORE_PRIOR );
}