Setting up a MySQL replica
This document is intended for building new production wiki databases. Following it while trying to build a one-off instance for a random app in your labs instance may result in untold suffering. It is a violation of federal law to use this product in a manner inconsistent with its labeling. |
New Server Setup
Hardware Raid
Ensure hardware raid is properly configured (raid-10, 256k strip, writeback cache, no read ahead)
root@db59:~# megacli -LDInfo -lALL -aALL | egrep "Level|Current Cache|Strip" RAID Level: Primary-1, Secondary-0, RAID Level Qualifier-0 Strip Size: 256kB Current Cache Policy: WriteBack, ReadAheadNone, Direct, No Write Cache if Bad BBU
If cache policy says 'ReadAdaptive' instead of 'ReadAheadNone', run megacli -LDSetProp NORA -Lall -Aall
XFS
A newly imaged server should have LVM setup correctly, with /dev/mapper/tank-data
mounted at /srv
. Ensure:
mkfs.xfs -f -d sunit=512,swidth=4096 -L data /dev/mapper/tank-data
/etc/fstab
mount options for/srv
fromdefaults
tonoatime,nobarrier
Puppet
Make sure server is in the correct groups in site.pp
node /db(32|36|38|59|60|63|69|70)\.pmtpa\.wmnet/ { if $hostname == "db59" { class { role::coredb::s1 : mariadb => true } } else { include role::coredb::s1 } }
Make sure the server is included in the regex for appropriate datacenter in hieradata/regex.yaml:
mysql_eqiad: __regex: !ruby/regexp /^(db10[0-9][0-9]|dbstore100[1-2]|dbproxy100[1-8]|es101[1-9]|labsdb100[1-8])\.eqiad\.wmnet$/ cluster: mysql mysql_codfw: __regex: !ruby/regexp /^(db20[0-9][0-9]|dbstore200[1-2]|es201[1-9])\.codfw\.wmnet$/ cluster: mysql
Make sure the server is defined in the correct shard section of the topology hash in role/coredb.pp. If the server is intended to be an lvm snapshot host, add it to the snapshot section. Do this last, after replication is configured and caught up.
's1' => { 'hosts' => { 'pmtpa' => [ 'db32', 'db36', 'db38', 'db59', 'db60', 'db63', 'db67', 'db69', 'db70' ], 'eqiad' => [ 'db1001', 'db1017', 'db1042', 'db1043', 'db1047', 'db1049', 'db1050'] }, 'primary_site' => $::mw_primary, 'masters' => { 'pmtpa' => "db63", 'eqiad' => "db1017" }, 'snapshot' => [ "db32", "db1050" ], 'no_master' => [ 'db67', 'db1047' ] },
mysql servers should be added to X property on hiera:path
Transferring Data
On New/Intended Slave
- ensure puppet runs cleanly
cd /srv/sqldata
nc -l -p 9210 | tar xvi
On Existing DB
This process is only intended for databases using only InnoDB tables!
- Select a source slave based on the intended use of the new slave.
- If you are creating a slave in the active datacenter intended for site production, use either the secondary master in the failover datacenter which can be found via dns (
host sX-secondary
) or an active production slave. This way replication data will be based on the active write master. - If creating a slave in the failover datacenter, or for analytics/non-site use in any datacenter, select a slave in the alternate datacenter. Replication in this case needs to come from the secondary, not the live write master.
- If you are creating a slave in the active datacenter intended for site production, use either the secondary master in the failover datacenter which can be found via dns (
innobackupex-1.5.1 --stream=tar /srv/sqldata --user=root --slave-info | nc NEW-SERVER 9210
- on stretch,
innobackupex-1.5.1
is replaced bymariabackup --innobackupex
- This results in a brief write lock towards the end of the process while the table definition files (but not data) are copied. For enwiki, this is around 200Mb of data. For this reason, this shouldn't be run on a write master if slaves are available.
- on stretch,
On New Slave, After xtrabackup
Do this before starting mysql!
innobackupex-1.5.1 --apply-log --use-memory=22G /srv/sqldata
chown -R mysql: /srv
/etc/init.d/mysql start
- tail the error log in /srv/sqldata and check for any errors
Starting Replication
- Check /srv/sqldata/xtrabackup_slave_info on the new host, it provides a partial CHANGE MASTER statement based on whichever host the target was replicating from. If this is correct, use this, adding MASTER_HOST and the repl account/password portions that are missing.
- e.g.
CHANGE MASTER to MASTER_USER='repl', MASTER_PASSWORD='...', MASTER_PORT=3306, MASTER_HOST='deployment-db1', MASTER_LOG_FILE='deployment-db1-bin.000026', MASTER_LOG_POS=191406295;
- e.g.
- If building a prod slave and had to run the hot backup from the master, use the information in /srv/sqldata/xtrabackup_binlog_info as slave_info won't exists.
- If you are building a failover slave, or something for analytics and copied from the secondary master, xtrabackup_slave_info will point to the active master; use xtrabackup_binlog_info instead.
- Important: If a production slave, this should point to the correct binlog position on the actual write master at which to start replication. If creating a slave in the failover datacenter or for analytics, make sure you have replication information for the second level master. Do not point these dbs to the active master!
Post Replication
- If part of a cluster that uses heartbeat replication monitoring, restart:
/etc/init.d/pt-heartbeat restart
Adding to Production
- Edit /home/w/common/wmf-config/db.php
- Make sure the IP address mapping is present in hostsByName[]
- Add to the appropriate shard in sectionLoads[]
- Initially add with a low weight to give it time to warm up and deply.
- Ensure the db operates well (check err and slow logs on the db, and db-error.log on fenari) and that replication keeps up under load.
- Once warm, raise to its full load level, typically the same as other slaves of the same hardware type, or greater depending on capacity.
Slaves Not In Active Production (db.php)
Make sure they'll receive schema migrations
- Slaves of the production cluster that don't belong in db.php still need to get schema migrations whenever they are applied in prod in order to keep replicating.
- Make sure they're added to the correct section in fenari:/home/w/common/wmf-config/db-secondary.php - it is an override for $wgLBFactoryConf['sectionLoads'] pointing only to slaves not used by the live MW site.
Making use-specific tweaks
Some DBs have differences from the normally generated config. These are applied via the puppet generated my.cnf, and further use case changes for prod slaves should be made similarly. This outlines what we do for the research slaves.
Research Slave
Note: These tweaks are reflected in puppet within mysql.pp as $research_dbs
- Hosts: db42, db1047
- Purpose: slaves of the s1 cluster dedicated to intense queries by the Summer of Research team (aka community intern statisticians).
- Contact:
- Tweaks:
- no binlog
- innodb-locks-unsafe-for-binlog
- slave_transaction_retries = very high