Avoid breaking DB transactions in SqlBagOStuff

* Callers still sees some decent time ordering since writes block
  until committed. This will not blindly flush transactions though.
* Basically reverts 59e8032

Change-Id: Ib9a91ac023f8e3fafb0bf0eef9dca6e31b867be9
This commit is contained in:
Aaron Schulz 2014-07-15 19:07:58 -07:00
parent 74c66cd9cb
commit d9385014fe

View file

@ -238,7 +238,12 @@ class SqlBagOStuff extends BagOStuff {
$res = $db->select( $tableName,
array( 'keyname', 'value', 'exptime' ),
array( 'keyname' => $tableKeys ),
__METHOD__ );
__METHOD__,
// Approximate write-on-the-fly BagOStuff API via blocking.
// This approximation fails if a ROLLBACK happens (which is rare).
// We do not want to flush the TRX as that can break callers.
$db->trxLevel() ? array( 'LOCK IN SHARE MODE' ) : array()
);
foreach ( $res as $row ) {
$row->serverIndex = $serverIndex;
$row->tableName = $tableName;
@ -258,13 +263,11 @@ class SqlBagOStuff extends BagOStuff {
$db = $this->getDB( $row->serverIndex );
if ( $this->isExpired( $db, $row->exptime ) ) { // MISS
$this->debug( "get: key has expired, deleting" );
$db->commit( __METHOD__, 'flush' );
# Put the expiry time in the WHERE condition to avoid deleting a
# newly-inserted value
$db->delete( $row->tableName,
array( 'keyname' => $key, 'exptime' => $row->exptime ),
__METHOD__ );
$db->commit( __METHOD__, 'flush' );
} else { // HIT
$values[$key] = $this->unserialize( $db->decodeBlob( $row->value ) );
}
@ -327,14 +330,12 @@ class SqlBagOStuff extends BagOStuff {
}
try {
$db->commit( __METHOD__, 'flush' );
$db->replace(
$tableName,
array( 'keyname' ),
$rows,
__METHOD__
);
$db->commit( __METHOD__, 'flush' );
} catch ( DBError $e ) {
$this->handleWriteError( $e, $serverIndex );
$result = false;
@ -374,7 +375,6 @@ class SqlBagOStuff extends BagOStuff {
$encExpiry = $db->timestamp( $exptime );
}
$db->commit( __METHOD__, 'flush' );
// (bug 24425) use a replace if the db supports it instead of
// delete/insert to avoid clashes with conflicting keynames
$db->replace(
@ -385,7 +385,6 @@ class SqlBagOStuff extends BagOStuff {
'value' => $db->encodeBlob( $this->serialize( $value ) ),
'exptime' => $encExpiry
), __METHOD__ );
$db->commit( __METHOD__, 'flush' );
} catch ( DBError $e ) {
$this->handleWriteError( $e, $serverIndex );
return false;
@ -419,7 +418,6 @@ class SqlBagOStuff extends BagOStuff {
}
$encExpiry = $db->timestamp( $exptime );
}
$db->commit( __METHOD__, 'flush' );
// (bug 24425) use a replace if the db supports it instead of
// delete/insert to avoid clashes with conflicting keynames
$db->update(
@ -435,7 +433,6 @@ class SqlBagOStuff extends BagOStuff {
),
__METHOD__
);
$db->commit( __METHOD__, 'flush' );
} catch ( DBQueryError $e ) {
$this->handleWriteError( $e, $serverIndex );
@ -454,12 +451,10 @@ class SqlBagOStuff extends BagOStuff {
list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
try {
$db = $this->getDB( $serverIndex );
$db->commit( __METHOD__, 'flush' );
$db->delete(
$tableName,
array( 'keyname' => $key ),
__METHOD__ );
$db->commit( __METHOD__, 'flush' );
} catch ( DBError $e ) {
$this->handleWriteError( $e, $serverIndex );
return false;
@ -478,7 +473,6 @@ class SqlBagOStuff extends BagOStuff {
try {
$db = $this->getDB( $serverIndex );
$step = intval( $step );
$db->commit( __METHOD__, 'flush' );
$row = $db->selectRow(
$tableName,
array( 'value', 'exptime' ),
@ -487,14 +481,12 @@ class SqlBagOStuff extends BagOStuff {
array( 'FOR UPDATE' ) );
if ( $row === false ) {
// Missing
$db->commit( __METHOD__, 'flush' );
return null;
}
$db->delete( $tableName, array( 'keyname' => $key ), __METHOD__ );
if ( $this->isExpired( $db, $row->exptime ) ) {
// Expired, do not reinsert
$db->commit( __METHOD__, 'flush' );
return null;
}
@ -512,7 +504,6 @@ class SqlBagOStuff extends BagOStuff {
// Race condition. See bug 28611
$newValue = null;
}
$db->commit( __METHOD__, 'flush' );
} catch ( DBError $e ) {
$this->handleWriteError( $e, $serverIndex );
return null;
@ -603,7 +594,6 @@ class SqlBagOStuff extends BagOStuff {
$maxExpTime = $row->exptime;
}
$db->commit( __METHOD__, 'flush' );
$db->delete(
$this->getTableNameByShard( $i ),
array(
@ -612,7 +602,6 @@ class SqlBagOStuff extends BagOStuff {
'keyname' => $keys
),
__METHOD__ );
$db->commit( __METHOD__, 'flush' );
if ( $progressCallback ) {
if ( intval( $totalSeconds ) === 0 ) {
@ -645,9 +634,7 @@ class SqlBagOStuff extends BagOStuff {
try {
$db = $this->getDB( $serverIndex );
for ( $i = 0; $i < $this->shards; $i++ ) {
$db->commit( __METHOD__, 'flush' );
$db->delete( $this->getTableNameByShard( $i ), '*', __METHOD__ );
$db->commit( __METHOD__, 'flush' );
}
} catch ( DBError $e ) {
$this->handleWriteError( $e, $serverIndex );
@ -775,12 +762,10 @@ class SqlBagOStuff extends BagOStuff {
}
for ( $i = 0; $i < $this->shards; $i++ ) {
$db->commit( __METHOD__, 'flush' );
$db->query(
'CREATE TABLE ' . $db->tableName( $this->getTableNameByShard( $i ) ) .
' LIKE ' . $db->tableName( 'objectcache' ),
__METHOD__ );
$db->commit( __METHOD__, 'flush' );
}
}
}