Page MenuHomePhabricator

Build a way to duplicate a whole wiki from one section to another
Open, MediumPublic

Description

It would be really nice to make MW be able to copy a whole wiki from one cluster to another. We already do similar work on table level (during table normalizations such as T300222: Implement normalizing MediaWiki link tables) and planning to even expand on duplicating full tables (T408137: Build a write duplicator system in mediawiki core) and expanding it to all of tables of a Wiki is not that much different.

Use cases:

  • Merging two sections by moving all wikis (one by one) from one section to another which can save a lot of resources in terms of money, power consumption, CO2, Hardware, engineering time, etc.
  • Moving closed wikis to a dedicated archive cluster with much smaller capacity to free up s3 and provide significant redaction in terms of number of files opened by the mariadb daemon.
  • Making the infra much more elastic. If a wiki becomes a noisy neighbor, easily move that to another section. We move replicas from one section to another using a cookbook and some puppet changes, I dream of a day we can move a wiki from one section to another with that ease.
  • (Maybe) Renaming a database. To ease T172035: Blockers for Wikimedia wiki domain renaming

Technical proposal:

  • This can't be done on MariaDB level. It should be done on MediaWiki level. We should be able to mediawiki to duplicate every write it sees for wiki X from one master to another.
    • It should be also automatically notice differences and heal the secondary cluster from the primary. So for example, if a row is being updated in the primary cluster that doesn't exist in secondary cluster, it should be able to read the data from primary, insert the row and then update it.
    • Making auto_increment inserts work will be quite fun.
  • There should be a mw maint script to go through all tables and duplicate the data.

Notes:

  • Moving a small wiki can be easily done with this idea, it shouldn't even take more than half an hour to move a small wiki from one cluster to another.
  • Moving should be done one wiki at a time. Otherwise, the extra amount of writes will be too much for the target cluster.
  • For very large wikis, very likely we won't be able to add the extra updates while copying terabytes of data so it doesn't make sense to look it this proposal thinking of moving enwiki or wikidatawiki. Similarly if a wiki grows so big that would require a dedicated cluster, it'd be much simpler and safer to do the usual cluster split we have done many times.
  • We definitely should start with very small wikis first and then move forward with larger wikis.

Open question:

  • Maybe there is an off the shelf library in MySQL/MariaDB ecosystem that can do it (similar to pt-online-schema-change)?

Event Timeline

Marostegui moved this task from Triage to Refine on the DBA board.

For closed wikis (normally small) we can directly do the import on the replicas and then on the master (it may take time, but it is doable).

The problem with active wikis would be the first import (unless you are planning to read all rows + insert on the final new wiki destination which would only have an empty table layout?), if they have not much activity we can do the above, and THEN we'd need to start replication from the upstream section: say we need to move a wiki from s3 to s5. The steps would be:

  • Take a logical mysqldump from the s3 wiki
  • Place it on all the replicas in s5 (if it is tiny, we can simply place it on the master and deal with the small lag).
  • Here is where the juicy part would start:
    • We need to configure replication on the primary s5 master to replicate up to the position where the mysqldump was taken (if it is small enough, there shouldn't be many transactions - but again this could create lag).

I understand that your idea would be to avoid the replication part and use MW to start copying the buffered transactions from that point in time where the mysqldump was taken to the current time and THEN duplicate each write until the wiki is ready to be split?

My idea is a bit different and much crazier. Let's say I want to move labswiki from s6 to s5:

  • Create labswiki database in s5 manually.
  • Create all tables empty manually (maybe that can be later also automated but wikiuser doesn't have CREATE grant)
  • Turn on the config in mw which would immediately start duplicating all write queries between two clusters.
    • With exception of the ones involving auto_increment in which it has to first get the id from s6 db and insert with that id set (so it's duplication but it involves extra field set). I assume anything relying on RAND() or date functions would have to be treated the same. See it more like MW-level SBR.
    • Some write queries might fail (for example when it tries to update a page id row while that page row doesn't exist yet) but that's fine. (you'll see why).
  • Run a mw maint script that would go through every row in each table, like db-compare and compares them. If a row is different, the source of truth is the s6 and we will update the s5 row accordingly. I assume we might want to lock the rows on both clusters before doing any writes.
  • Run it multiple times. Just to be sure all holes are covered.
  • Flip the switch in mw which would still write to both clusters but now the source of truth is s5, not s6. Also, reads switch to happen from s5 now instead of s6.
  • Once we are comfortable things are fine. Remove the "s6" as the replica/secondary cluster of this wiki in mw config. So mediawiki stops duplicating writes.
  • Once we are really comfortable. Drop the database from s6.

With this, you don't need any RO time at all. You don't need to use any backup/recovery or mysqldump at all or go through transactions. MediaWiki will just compare rows live via a maint script and slowly builds the wiki's database. This is specially for small wikis would be quite nice since the whole process won't take longer than an hour and we would easily move one wiki from one cluster to another.

Would anything need to be done on parsercache or external store level? I assume no?
We should definitely put lots of safety checks in place to ensure consistency is preserved and that not a single row is lost.

I am a bit worried with a possible race condition that could happen if we don't use RO.
When we switch the config in MW and deploy, it won't arrive at the same time everywhere, meaning some hosts may start consider source of truth s5 while others already have s6, what would happen in that situation?

I don't think having RO is bad per se, if it is just a few minutes to ensure everything is exactly the same (especially with large tables).

Would anything need to be done on parsercache or external store level? I assume no?

Nope, they are only identified via dbname. Otherwise, when we moved wikidata out of s5, things would have had broken royally.

We should definitely put lots of safety checks in place to ensure consistency is preserved and that not a single row is lost.

I wonder if we can run db-compare too between two sections. One fun complexity is rows that are deleted in the source of truth and must be deleted on secondary but haven't been deleted.

I am a bit worried with a possible race condition that could happen if we don't use RO.
When we switch the config in MW and deploy, it won't arrive at the same time everywhere, meaning some hosts may start consider source of truth s5 while others already have s6, what would happen in that situation?

That should be fine and data should stay consistent. At least in paper but if writes are too many, it can cause issues e.g. collision of auto_increment id

I don't think having RO is bad per se, if it is just a few minutes to ensure everything is exactly the same (especially with large tables).

Given above, I think RO won't be needed for small wikis, but we definitely should do RO for frwiki or somewhat larger wikis during the mw deploy.

Another point to consider: https://meta.wikimedia.org/wiki/Wikimedia_Foundation_Community_Affairs_Committee/Sister_Projects_Task_Force/Results_of_the_consultation_about_Wikispore_and_Wikinews#Wikinews it's very likely most if not all wikinews projects will be closed and archived which means number of closed wikis will reach ~170. Having a small archive cluster that we could move all of these wikis to would help s3 a lot.

Another point to consider: https://meta.wikimedia.org/wiki/Wikimedia_Foundation_Community_Affairs_Committee/Sister_Projects_Task_Force/Results_of_the_consultation_about_Wikispore_and_Wikinews#Wikinews it's very likely most if not all wikinews projects will be closed and archived which means number of closed wikis will reach ~170. Having a small archive cluster that we could move all of these wikis to would help s3 a lot.

That's great - however, remember that for closed projects (with no writes) this whole process is way way easier.

Another point to consider: https://meta.wikimedia.org/wiki/Wikimedia_Foundation_Community_Affairs_Committee/Sister_Projects_Task_Force/Results_of_the_consultation_about_Wikispore_and_Wikinews#Wikinews it's very likely most if not all wikinews projects will be closed and archived which means number of closed wikis will reach ~170. Having a small archive cluster that we could move all of these wikis to would help s3 a lot.

That's great - however, remember that for closed projects (with no writes) this whole process is way way easier.

There will be some writes, stewards can still edit closed projects plus there are db writes for linter and some other stuff happening but obviously, they are quite low in frequency and no matter how we are planning to move them (mw or mysql), it's going to be easy.