public function doUpdate() { # Page may already be deleted, so don't just getId() $id = $this->pageId; # Delete restrictions for it $this->mDb->delete('page_restrictions', array('pr_page' => $id), __METHOD__); # Fix category table counts $cats = $this->mDb->selectFieldValues('categorylinks', 'cl_to', array('cl_from' => $id), __METHOD__); $this->page->updateCategoryCounts(array(), $cats); # If using cascading deletes, we can skip some explicit deletes if (!$this->mDb->cascadingDeletes()) { # Delete outgoing links $this->mDb->delete('pagelinks', array('pl_from' => $id), __METHOD__); $this->mDb->delete('imagelinks', array('il_from' => $id), __METHOD__); $this->mDb->delete('categorylinks', array('cl_from' => $id), __METHOD__); $this->mDb->delete('templatelinks', array('tl_from' => $id), __METHOD__); $this->mDb->delete('externallinks', array('el_from' => $id), __METHOD__); $this->mDb->delete('langlinks', array('ll_from' => $id), __METHOD__); $this->mDb->delete('iwlinks', array('iwl_from' => $id), __METHOD__); $this->mDb->delete('redirect', array('rd_from' => $id), __METHOD__); $this->mDb->delete('page_props', array('pp_page' => $id), __METHOD__); } # If using cleanup triggers, we can skip some manual deletes if (!$this->mDb->cleanupTriggers()) { $title = $this->page->getTitle(); # Find recentchanges entries to clean up... $rcIdsForTitle = $this->mDb->selectFieldValues('recentchanges', 'rc_id', array('rc_type != ' . RC_LOG, 'rc_namespace' => $title->getNamespace(), 'rc_title' => $title->getDBkey()), __METHOD__); $rcIdsForPage = $this->mDb->selectFieldValues('recentchanges', 'rc_id', array('rc_type != ' . RC_LOG, 'rc_cur_id' => $id), __METHOD__); # T98706: delete PK to avoid lock contention with RC delete log insertions $rcIds = array_merge($rcIdsForTitle, $rcIdsForPage); if ($rcIds) { $this->mDb->delete('recentchanges', array('rc_id' => $rcIds), __METHOD__); } } }
public function doUpdate() { $services = MediaWikiServices::getInstance(); $config = $services->getMainConfig(); $lbFactory = $services->getDBLoadBalancerFactory(); $batchSize = $config->get('UpdateRowsPerQuery'); // Page may already be deleted, so don't just getId() $id = $this->pageId; if ($this->ticket) { // Make sure all links update threads see the changes of each other. // This handles the case when updates have to batched into several COMMITs. $scopedLock = LinksUpdate::acquirePageLock($this->getDB(), $id); } $title = $this->page->getTitle(); $dbw = $this->getDB(); // convenience // Delete restrictions for it $dbw->delete('page_restrictions', ['pr_page' => $id], __METHOD__); // Fix category table counts $cats = $dbw->selectFieldValues('categorylinks', 'cl_to', ['cl_from' => $id], __METHOD__); $catBatches = array_chunk($cats, $batchSize); foreach ($catBatches as $catBatch) { $this->page->updateCategoryCounts([], $catBatch, $id); if (count($catBatches) > 1) { $lbFactory->commitAndWaitForReplication(__METHOD__, $this->ticket, ['wiki' => $dbw->getWikiID()]); } } // Refresh the category table entry if it seems to have no pages. Check // master for the most up-to-date cat_pages count. if ($title->getNamespace() === NS_CATEGORY) { $row = $dbw->selectRow('category', ['cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files'], ['cat_title' => $title->getDBkey(), 'cat_pages <= 0'], __METHOD__); if ($row) { Category::newFromRow($row, $title)->refreshCounts(); } } $this->batchDeleteByPK('pagelinks', ['pl_from' => $id], ['pl_from', 'pl_namespace', 'pl_title'], $batchSize); $this->batchDeleteByPK('imagelinks', ['il_from' => $id], ['il_from', 'il_to'], $batchSize); $this->batchDeleteByPK('categorylinks', ['cl_from' => $id], ['cl_from', 'cl_to'], $batchSize); $this->batchDeleteByPK('templatelinks', ['tl_from' => $id], ['tl_from', 'tl_namespace', 'tl_title'], $batchSize); $this->batchDeleteByPK('externallinks', ['el_from' => $id], ['el_id'], $batchSize); $this->batchDeleteByPK('langlinks', ['ll_from' => $id], ['ll_from', 'll_lang'], $batchSize); $this->batchDeleteByPK('iwlinks', ['iwl_from' => $id], ['iwl_from', 'iwl_prefix', 'iwl_title'], $batchSize); // Delete any redirect entry or page props entries $dbw->delete('redirect', ['rd_from' => $id], __METHOD__); $dbw->delete('page_props', ['pp_page' => $id], __METHOD__); // Find recentchanges entries to clean up... $rcIdsForTitle = $dbw->selectFieldValues('recentchanges', 'rc_id', ['rc_type != ' . RC_LOG, 'rc_namespace' => $title->getNamespace(), 'rc_title' => $title->getDBkey(), 'rc_timestamp < ' . $dbw->addQuotes($dbw->timestamp($this->timestamp))], __METHOD__); $rcIdsForPage = $dbw->selectFieldValues('recentchanges', 'rc_id', ['rc_type != ' . RC_LOG, 'rc_cur_id' => $id], __METHOD__); // T98706: delete by PK to avoid lock contention with RC delete log insertions $rcIdBatches = array_chunk(array_merge($rcIdsForTitle, $rcIdsForPage), $batchSize); foreach ($rcIdBatches as $rcIdBatch) { $dbw->delete('recentchanges', ['rc_id' => $rcIdBatch], __METHOD__); if (count($rcIdBatches) > 1) { $lbFactory->commitAndWaitForReplication(__METHOD__, $this->ticket, ['wiki' => $dbw->getWikiID()]); } } // Commit and release the lock (if set) ScopedCallback::consume($scopedLock); }
public function doUpdate() { # Page may already be deleted, so don't just getId() $id = $this->pageId; // Make sure all links update threads see the changes of each other. // This handles the case when updates have to batched into several COMMITs. $scopedLock = LinksUpdate::acquirePageLock($this->mDb, $id); # Delete restrictions for it $this->mDb->delete('page_restrictions', ['pr_page' => $id], __METHOD__); # Fix category table counts $cats = $this->mDb->selectFieldValues('categorylinks', 'cl_to', ['cl_from' => $id], __METHOD__); $this->page->updateCategoryCounts([], $cats); # If using cascading deletes, we can skip some explicit deletes if (!$this->mDb->cascadingDeletes()) { # Delete outgoing links $this->mDb->delete('pagelinks', ['pl_from' => $id], __METHOD__); $this->mDb->delete('imagelinks', ['il_from' => $id], __METHOD__); $this->mDb->delete('categorylinks', ['cl_from' => $id], __METHOD__); $this->mDb->delete('templatelinks', ['tl_from' => $id], __METHOD__); $this->mDb->delete('externallinks', ['el_from' => $id], __METHOD__); $this->mDb->delete('langlinks', ['ll_from' => $id], __METHOD__); $this->mDb->delete('iwlinks', ['iwl_from' => $id], __METHOD__); $this->mDb->delete('redirect', ['rd_from' => $id], __METHOD__); $this->mDb->delete('page_props', ['pp_page' => $id], __METHOD__); } # If using cleanup triggers, we can skip some manual deletes if (!$this->mDb->cleanupTriggers()) { $title = $this->page->getTitle(); # Find recentchanges entries to clean up... $rcIdsForTitle = $this->mDb->selectFieldValues('recentchanges', 'rc_id', ['rc_type != ' . RC_LOG, 'rc_namespace' => $title->getNamespace(), 'rc_title' => $title->getDBkey()], __METHOD__); $rcIdsForPage = $this->mDb->selectFieldValues('recentchanges', 'rc_id', ['rc_type != ' . RC_LOG, 'rc_cur_id' => $id], __METHOD__); # T98706: delete PK to avoid lock contention with RC delete log insertions $rcIds = array_merge($rcIdsForTitle, $rcIdsForPage); if ($rcIds) { $this->mDb->delete('recentchanges', ['rc_id' => $rcIds], __METHOD__); } } $this->mDb->onTransactionIdle(function () use(&$scopedLock) { // Release the lock *after* the final COMMIT for correctness ScopedCallback::consume($scopedLock); }); }