summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt2
-rw-r--r--includes/database/query.inc76
2 files changed, 34 insertions, 44 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index d0bdb544f..73975a856 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,8 @@
Drupal 7.25, xxxx-xx-xx (development version)
-----------------------
+- Fixed a bug in the database API that caused frequent deadlock errors when
+ running merge queries on some servers.
- Performance improvement: Prevent block rehashing from writing blocks to the
database on every cache clear and cron run when the blocks have not changed.
This fix results in an extra 'saved' key which is added and set to TRUE for
diff --git a/includes/database/query.inc b/includes/database/query.inc
index ce242beb7..8af91c2d7 100644
--- a/includes/database/query.inc
+++ b/includes/database/query.inc
@@ -1606,55 +1606,43 @@ class MergeQuery extends Query implements QueryConditionInterface {
}
public function execute() {
- // Wrap multiple queries in a transaction, if the database supports it.
- $transaction = $this->connection->startTransaction();
- try {
- if (!count($this->condition)) {
- throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
- }
- $select = $this->connection->select($this->conditionTable)
- ->condition($this->condition)
- ->forUpdate();
- $select->addExpression('1');
- if (!$select->execute()->fetchField()) {
- try {
- $insert = $this->connection->insert($this->table)->fields($this->insertFields);
- if ($this->defaultFields) {
- $insert->useDefaults($this->defaultFields);
- }
- $insert->execute();
- return MergeQuery::STATUS_INSERT;
- }
- catch (Exception $e) {
- // The insert query failed, maybe it's because a racing insert query
- // beat us in inserting the same row. Retry the select query, if it
- // returns a row, ignore the error and continue with the update
- // query below.
- if (!$select->execute()->fetchField()) {
- throw $e;
- }
+ if (!count($this->condition)) {
+ throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
+ }
+ $select = $this->connection->select($this->conditionTable)
+ ->condition($this->condition);
+ $select->addExpression('1');
+ if (!$select->execute()->fetchField()) {
+ try {
+ $insert = $this->connection->insert($this->table)->fields($this->insertFields);
+ if ($this->defaultFields) {
+ $insert->useDefaults($this->defaultFields);
}
+ $insert->execute();
+ return self::STATUS_INSERT;
}
- if ($this->needsUpdate) {
- $update = $this->connection->update($this->table)
- ->fields($this->updateFields)
- ->condition($this->condition);
- if ($this->expressionFields) {
- foreach ($this->expressionFields as $field => $data) {
- $update->expression($field, $data['expression'], $data['arguments']);
- }
+ catch (Exception $e) {
+ // The insert query failed, maybe it's because a racing insert query
+ // beat us in inserting the same row. Retry the select query, if it
+ // returns a row, ignore the error and continue with the update
+ // query below.
+ if (!$select->execute()->fetchField()) {
+ throw $e;
}
- $update->execute();
- return MergeQuery::STATUS_UPDATE;
}
}
- catch (Exception $e) {
- // Something really wrong happened here, bubble up the exception to the
- // caller.
- $transaction->rollback();
- throw $e;
- }
- // Transaction commits here where $transaction looses scope.
+ if ($this->needsUpdate) {
+ $update = $this->connection->update($this->table)
+ ->fields($this->updateFields)
+ ->condition($this->condition);
+ if ($this->expressionFields) {
+ foreach ($this->expressionFields as $field => $data) {
+ $update->expression($field, $data['expression'], $data['arguments']);
+ }
+ }
+ $update->execute();
+ return self::STATUS_UPDATE;
+ }
}
}