From 7f3d3df73abf141a7dd0b942b907bd2488c6a95e Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Mon, 10 Mar 2014 12:53:48 -0700 Subject: [PATCH] Further optimize User::saveOptions() by doing deletes by PRIMARY KEY * We do not care about gap locks here, just as in the case with new users. Races should be rare and are simply FWW. Change-Id: Ie483a2d5df501619acbd868bf894dfc6c911a753 --- includes/User.php | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/includes/User.php b/includes/User.php index e7283238ba..6d9f3724ee 100644 --- a/includes/User.php +++ b/includes/User.php @@ -4736,28 +4736,35 @@ class User { // Don't bother storing default values $defaultOption = self::getDefaultOption( $key ); if ( ( is_null( $defaultOption ) && - !( $value === false || is_null( $value ) ) ) || - $value != $defaultOption ) { + !( $value === false || is_null( $value ) ) ) || + $value != $defaultOption + ) { $insert_rows[] = array( - 'up_user' => $userId, - 'up_property' => $key, - 'up_value' => $value, - ); + 'up_user' => $userId, + 'up_property' => $key, + 'up_value' => $value, + ); } } $dbw = wfGetDB( DB_MASTER ); - $hasRows = $dbw->selectField( 'user_properties', '1', - array( 'up_user' => $userId ), __METHOD__ ); - - if ( $hasRows ) { - // Only do this delete if there is something there. A very large portion of + // Find and delete any prior preference rows... + $res = $dbw->select( 'user_properties', + array( 'up_property' ), array( 'up_user' => $userId ), __METHOD__ ); + $priorKeys = array(); + foreach ( $res as $row ) { + $priorKeys[] = $row->up_property; + } + if ( count( $priorKeys ) ) { + // Do the DELETE by PRIMARY KEY for prior rows. A very large portion of // calls to this function are for setting 'rememberpassword' for new accounts. - // Doing this delete for new accounts with no rows in the table rougly causes - // gap locks on [max user ID,+infinity) which causes high contention since many - // updates will pile up on each other since they are for higher (newer) user IDs. - $dbw->delete( 'user_properties', array( 'up_user' => $userId ), __METHOD__ ); + // Doing a blanket per-user DELETE for new accounts with no rows in the table + // causes gap locks on [max user ID,+infinity) which causes high contention since + // updates will pile up on each other as they are for higher (newer) user IDs. + $dbw->delete( 'user_properties', + array( 'up_user' => $userId, 'up_property' => $priorKeys ), __METHOD__ ); } + // Insert the new preference rows $dbw->insert( 'user_properties', $insert_rows, __METHOD__, array( 'IGNORE' ) ); } -- 2.20.1