Page MenuHomePhabricator

Schema updates on virtual domains are double-applied because updateRowExists() is called on the wrong DB domain
Open, Needs TriagePublicBUG REPORT

Description

When running update.php --doshared, updateRowExists() will be called with $this->db pointing to the virtual domain, and so it will always return false.
For the same reason, successful updates aren't logged by insertUpdateRow().

I've seen this happen in DatabaseUpdater::modifyFieldWithCondition() (e.g. the gb_id type change in globalblocks), probably affects other things too. ALTERs are usually idempotent, but it's easy to imagine situations in which this does serious damage.

Event Timeline

Addint MediaWiki-Core-Platform-Team for now since 1) CentralAuth and OAuth are affected, 2) this is serious enough that we should at least make sure to find an owner who picks it up.

Some possible approaches:

  1. Make sure we always use the wiki DB for updatelog table operations. It is the admin's responsibility to always use --doshared with the same wiki. Still an accident waiting to happen, we just shift the blame to the admin.
  2. Keep using the virtual domain but create the updatelog table automatically when it doesn't exist. Requires the updater to be able to create tables (or nag the admin about it), litters everything with updatelog tables, and makes moving a virtual domain from one DB to another more cumbersome.
  3. Introduce a configuration variable to appoint a primary wiki (or more generally, a DB) to use as the updatelog source. Changing that configuration variable will be cumbersome. Cannot handle some contrived situations that probably never happen in real life (we want wiki1 to use DB1 for virtual-domain-1 and DB1 for virtual-domain-2, wiki2 to use DB1 for virtual-domain-1 and DB2 for virtual-domain-2, and wiki3 to use DB2 for virtual-domain-1 and DB2 for virtual-domain-2).
  4. Introduce a configuration variable mapping virtual domains to updatelog sources (maybe make it part of the virtual domain data structure). Same as above but can handle contrived situations. Feels overengineered.
  5. Like #3 but add a column to updatelog which tracks the domain the update happened on, to make migrations easier. Probably not worth the effort?

Change #1324701 had a related patch set uploaded (by Pmiazga; author: Pmiazga):

[mediawiki/core@master] DNM: DatabaseUpdater: Create updatelog on shared virtual domains

https://gerrit.wikimedia.org/r/1324701

The patch I pushed - it was mostly me experimenting with Claude, decided to push it, - it creates the updatelog table and also adds some interesting thoughts regarding initial seeds

I talked to @matmarex a bit about it today and I think the simplest solution would be to introduce a "virtual-shared-updatelog" virtual domain in which simple setups simply fall back to the local db and larger places, can set the mapping in localsettings then anything that runs with "doshared", should try to get db connection with that domain. It's not cleanest solution but could work and reduces the chance of oopsies.

In the longer term, I welcome any changes to updatelog. It needs a decent clean up. My favorite thing is that we rely on markers to "guess" which version of mediawiki the database was last updated (and avoid updating from too old versions) and that means every time I have to find a random schema change to use as marker: https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1162633/2/maintenance/update.php ) WCPGW. So adding a column for "version that ran the update" would already be quite useful. I know it's not that related, it just bothers me a lot.