aboutsummaryrefslogtreecommitdiffstats
path: root/includes/block/DatabaseBlockStore.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/block/DatabaseBlockStore.php')
-rw-r--r--includes/block/DatabaseBlockStore.php13
1 files changed, 13 insertions, 0 deletions
diff --git a/includes/block/DatabaseBlockStore.php b/includes/block/DatabaseBlockStore.php
index c33157b58157..20f662e044d5 100644
--- a/includes/block/DatabaseBlockStore.php
+++ b/includes/block/DatabaseBlockStore.php
@@ -1044,6 +1044,7 @@ class DatabaseBlockStore {
$targetUserName = (string)$target;
$targetUserId = $target->getUserIdentity()->getId( $this->wikiId );
$targetConds = [ 'bt_user' => $targetUserId ];
+ $targetLockKey = $dbw->getDomainID() . ':block:u:' . $targetUserId;
} else {
$targetAddress = (string)$target;
$targetUserName = null;
@@ -1052,6 +1053,8 @@ class DatabaseBlockStore {
'bt_address' => $targetAddress,
'bt_auto' => $isAuto,
];
+ $targetLockKey = $dbw->getDomainID() . ':block:' .
+ ( $isAuto ? 'a' : 'i' ) . ':' . $targetAddress;
}
$condsWithCount = $targetConds;
@@ -1059,6 +1062,15 @@ class DatabaseBlockStore {
$condsWithCount['bt_count'] = $expectedTargetCount;
}
+ $dbw->lock( $targetLockKey, __METHOD__ );
+ $func = __METHOD__;
+ $dbw->onTransactionCommitOrIdle(
+ static function () use ( $dbw, $targetLockKey, $func ) {
+ $dbw->unlock( $targetLockKey, "$func.closure" );
+ },
+ __METHOD__
+ );
+
// This query locks the index gap when the target doesn't exist yet,
// so there is a risk of throttling adjacent block insertions,
// especially on small wikis which have larger gaps. If this proves to
@@ -1076,6 +1088,7 @@ class DatabaseBlockStore {
->select( [ 'bt_id', 'bt_count' ] )
->from( 'block_target' )
->where( $targetConds )
+ ->forUpdate()
->caller( __METHOD__ )
->fetchResultSet();
if ( $res->numRows() > 1 ) {