+ * @param int $flags
+ * @return bool
+ */
+ private function sanitizeConnectionFlags( $flags ) {
+ if ( ( $flags & self::CONN_TRX_AUTOCOMMIT ) === self::CONN_TRX_AUTOCOMMIT ) {
+ // Assuming all servers are of the same type (or similar), which is overwhelmingly
+ // the case, use the master server information to get the attributes. The information
+ // for $i cannot be used since it might be DB_REPLICA, which might require connection
+ // attempts in order to be resolved into a real server index.
+ $attributes = $this->getServerAttributes( $this->getWriterIndex() );
+ if ( $attributes[Database::ATTR_DB_LEVEL_LOCKING] ) {
+ // Callers sometimes want to (a) escape REPEATABLE-READ stateness without locking
+ // rows (e.g. FOR UPDATE) or (b) make small commits during a larger transactions
+ // to reduce lock contention. None of these apply for sqlite and using separate
+ // connections just causes self-deadlocks.
+ $flags &= ~self::CONN_TRX_AUTOCOMMIT;
+ $this->connLogger->info( __METHOD__ .
+ ': ignoring CONN_TRX_AUTOCOMMIT to avoid deadlocks.' );
+ }
+ }
+
+ return $flags;
+ }
+
+ /**
+ * @param IDatabase $conn
+ * @param int $flags
+ * @throws DBUnexpectedError
+ */
+ private function enforceConnectionFlags( IDatabase $conn, $flags ) {
+ if ( ( $flags & self::CONN_TRX_AUTOCOMMIT ) == self::CONN_TRX_AUTOCOMMIT ) {
+ if ( $conn->trxLevel() ) { // sanity
+ throw new DBUnexpectedError(
+ $conn,
+ 'Handle requested with CONN_TRX_AUTOCOMMIT yet it has a transaction'
+ );
+ }
+
+ $conn->clearFlag( $conn::DBO_TRX ); // auto-commit mode
+ }
+ }
+
+ /**