sql >> Databáze >  >> RDS >> Mysql

MySQL v cloudu – Online migrace z Amazon RDS na váš vlastní server:Část 2

Jak jsme viděli dříve, pro společnosti může být náročné přesunout svá data z RDS pro MySQL. V první části tohoto blogu jsme vám ukázali, jak nastavit vaše cílové prostředí na EC2 a vložit proxy vrstvu (ProxySQL) mezi vaše aplikace a RDS. V této druhé části vám ukážeme, jak provést skutečnou migraci dat na váš vlastní server a poté bez prostojů přesměrovat vaše aplikace na novou instanci databáze.

Kopírování dat z RDS

Jakmile provoz naší databáze běží přes ProxySQL, můžeme začít s přípravami na kopírování našich dat z RDS. Musíme to udělat, abychom mohli nastavit replikaci mezi RDS a naší instancí MySQL běžící na EC2. Jakmile to uděláme, nakonfigurujeme ProxySQL tak, aby přesměroval provoz z RDS do našeho MySQL/EC2.

Jak jsme diskutovali v prvním příspěvku na blogu v této sérii, jediný způsob, jak můžete získat data z RDS, je logický výpis. Bez přístupu k instanci nemůžeme používat žádné horké nástroje fyzického zálohování, jako je xtrabackup. Nemůžeme použít ani snímky, protože neexistuje způsob, jak ze snímku vytvořit něco jiného než novou instanci RDS.

Jsme omezeni na nástroje logického výpisu, proto by logickou možností bylo použít ke zpracování dat mydump/myloader. Naštěstí může mydumper vytvářet konzistentní zálohy, takže se na něj můžeme spolehnout, že poskytne binlogové souřadnice pro našeho nového otroka, ke kterému se může připojit. Hlavním problémem při vytváření replik RDS je zásada rotace binlogů – logický výpis a načítání může trvat i dny u větších (stovky gigabajtů) datových sad a po dobu celého tohoto procesu musíte uchovávat binlogy na instanci RDS. Jistě, můžete zvýšit uchování rotace binlogů na RDS (zavolejte mysql.rds_set_configuration('binlog retenční hodiny', 24); – můžete je ponechat až 7 dní), ale je mnohem bezpečnější to udělat jinak.

Než přistoupíme k vytváření výpisu, přidáme repliku do naší instance RDS.

Amazon RDS Dashboard Vytvoření repliky DB v RDS

Jakmile klikneme na tlačítko „Vytvořit přečtenou repliku“, spustí se snímek „hlavní“ repliky RDS. Bude použit k zajištění nového otroka. Proces může trvat hodiny, vše závisí na velikosti svazku, kdy byl naposledy pořízen snímek a výkonu svazku (io1/gp2? Magnetický? Kolik pIOPS má svazek?).

Hlavní replika RDS

Když je slave připraven (jeho stav se změnil na „dostupný“), můžeme se k němu přihlásit pomocí jeho koncového bodu RDS.

RDS Slave

Jakmile se přihlásíme, zastavíme replikaci na našem podřízeném zařízení – to zajistí, že hlavní server RDS nevyčistí binární protokoly a budou stále dostupné pro naši podřízenou jednotku EC2, jakmile dokončíme proces výpisu/znovu načtení.

mysql> CALL mysql.rds_stop_replication;
+---------------------------+
| Message                   |
+---------------------------+
| Slave is down or disabled |
+---------------------------+
1 row in set (1.02 sec)

Query OK, 0 rows affected (1.02 sec)

Nyní je konečně čas zkopírovat data do EC2. Nejprve musíme nainstalovat mydumper. Můžete jej získat z github:https://github.com/maxbube/mydumper. Proces instalace je poměrně jednoduchý a pěkně popsaný v souboru readme, takže se jím zde nebudeme zabývat. S největší pravděpodobností budete muset nainstalovat několik balíčků (uvedených v readme) a těžší je určit, který balíček obsahuje mysql_config - záleží na verzi MySQL (a někdy také verzi MySQL).

Jakmile budete mít mydump zkompilovaný a připravený k použití, můžete jej spustit:

[email protected]:~/mydumper# mkdir /tmp/rdsdump
[email protected]:~/mydumper# ./mydumper -h rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com -p tpccpass -u tpcc  -o /tmp/rdsdump  --lock-all-tables --chunk-filesize 100 --events --routines --triggers
. 

Vezměte prosím na vědomí --lock-all-tables, který zajišťuje, že snímek dat bude konzistentní a bude možné jej použít k vytvoření slave. Nyní musíme počkat, až mydumper dokončí svůj úkol.

Je vyžadován ještě jeden krok – nechceme obnovovat schéma mysql, ale potřebujeme zkopírovat uživatele a jejich granty. K tomu můžeme použít pt-show-grants:

[email protected]:~# wget http://percona.com/get/pt-show-grants
[email protected]:~# chmod u+x ./pt-show-grants
[email protected]:~# ./pt-show-grants -h rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com -u tpcc -p tpccpass > grants.sql

Příklad pt-show-grants může vypadat takto:

-- Grants for 'sbtest'@'%'
CREATE USER IF NOT EXISTS 'sbtest'@'%';
ALTER USER 'sbtest'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*2AFD99E79E4AA23DE141540F4179F64FFB3AC521' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE USER, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, PROCESS, REFERENCES, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SELECT, SHOW DATABASES, SHOW VIEW, TRIGGER, UPDATE ON *.* TO 'sbtest'@'%';

Je na vás, abyste si vybrali, kteří uživatelé mají být zkopírováni do vaší instance MySQL/EC2. Nemá smysl to dělat pro všechny. Například uživatelé root nemají oprávnění „SUPER“ na RDS, takže je lepší je znovu vytvořit od začátku. Co potřebujete zkopírovat, jsou granty pro uživatele vaší aplikace. Potřebujeme také zkopírovat uživatele používané ProxySQL (v našem případě proxysql-monitor).

Vkládání dat do vaší instance MySQL/EC2

Jak je uvedeno výše, nechceme obnovovat systémová schémata. Proto přesuneme soubory související s těmito schématy z našeho adresáře mydump:

[email protected]:~# mkdir /tmp/rdsdump_sys/
[email protected]:~# mv /tmp/rdsdump/mysql* /tmp/rdsdump_sys/
[email protected]:~# mv /tmp/rdsdump/sys* /tmp/rdsdump_sys/

Když jsme s tím hotovi, je čas začít načítat data do instance MySQL/EC2:

[email protected]:~/mydumper# ./myloader -d /tmp/rdsdump/ -u tpcc -p tpccpass -t 4 --overwrite-tables -h 172.30.4.238

Vezměte prosím na vědomí, že jsme použili čtyři vlákna (-t 4) - ujistěte se, že toto nastavíte na cokoli, co má ve vašem prostředí smysl. Je to všechno o nasycení cílové instance MySQL – buď CPU nebo I/O, v závislosti na úzkém hrdle. Chceme z toho vymáčknout co nejvíce, abychom zajistili, že jsme k načtení dat využili všechny dostupné zdroje.

Po načtení hlavních dat je třeba provést další dva kroky, oba se týkají vnitřních částí RDS a oba mohou přerušit naši replikaci. Za prvé, RDS obsahuje několik tabulek rds_* ve schématu mysql. Chceme je načíst pro případ, že některé z nich používá RDS – replikace se přeruší, pokud je náš slave nebude mít. Můžeme to udělat následujícím způsobem:

[email protected]:~/mydumper# for i in $(ls -alh /tmp/rdsdump_sys/ | grep rds | awk '{print $9}') ; do echo $i ;  mysql -ppass -uroot  mysql < /tmp/rdsdump_sys/$i ; done
mysql.rds_configuration-schema.sql
mysql.rds_configuration.sql
mysql.rds_global_status_history_old-schema.sql
mysql.rds_global_status_history-schema.sql
mysql.rds_heartbeat2-schema.sql
mysql.rds_heartbeat2.sql
mysql.rds_history-schema.sql
mysql.rds_history.sql
mysql.rds_replication_status-schema.sql
mysql.rds_replication_status.sql
mysql.rds_sysinfo-schema.sql

Podobný problém je s tabulkami časových pásem, musíme je načíst pomocí dat z instance RDS:

[email protected]:~/mydumper# for i in $(ls -alh /tmp/rdsdump_sys/ | grep time_zone | grep -v schema | awk '{print $9}') ; do echo $i ;  mysql -ppass -uroot  mysql < /tmp/rdsdump_sys/$i ; done
mysql.time_zone_name.sql
mysql.time_zone.sql
mysql.time_zone_transition.sql
mysql.time_zone_transition_type.sql

Až bude vše připraveno, můžeme nastavit replikaci mezi RDS (master) a naší instancí MySQL/EC2 (slave).

Nastavení replikace

Mydump, když provádí konzistentní výpis, zapíše pozici binárního protokolu. Tato data můžeme najít v souboru s názvem metadata v adresáři výpisu. Pojďme se na to podívat, pozici pak použijeme k nastavení replikace.

[email protected]:~/mydumper# cat /tmp/rdsdump/metadata
Started dump at: 2017-02-03 16:17:29
SHOW SLAVE STATUS:
    Host: 10.1.4.180
    Log: mysql-bin-changelog.007079
    Pos: 10537102
    GTID:

Finished dump at: 2017-02-03 16:44:46

Poslední věc, kterou nám chybí, je uživatel, kterého bychom mohli použít k nastavení našeho otroka. Vytvořme jeden na instanci RDS:

[email protected]:~# mysql -ppassword -h rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com
mysql> CREATE USER IF NOT EXISTS 'rds_rpl'@'%' IDENTIFIED BY 'rds_rpl_pass';
Query OK, 0 rows affected (0.04 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO 'rds_rpl'@'%';
Query OK, 0 rows affected (0.01 sec)

Nyní je čas podřídit náš server MySQL/EC2 instanci RDS:

mysql> CHANGE MASTER TO MASTER_HOST='rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com', MASTER_USER='rds_rpl', MASTER_PASSWORD='rds_rpl_pass', MASTER_LOG_FILE='mysql-bin-changelog.007079', MASTER_LOG_POS=10537102;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> START SLAVE;
Query OK, 0 rows affected (0.02 sec)
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Queueing master event to the relay log
                  Master_Host: rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com
                  Master_User: rds_rpl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-changelog.007080
          Read_Master_Log_Pos: 13842678
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 20448
        Relay_Master_Log_File: mysql-bin-changelog.007079
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 10557220
              Relay_Log_Space: 29071382
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 258726
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1237547456
                  Master_UUID: b5337d20-d815-11e6-abf1-120217bb3ac2
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: System lock
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.01 sec)

Posledním krokem bude přepnutí našeho provozu z instance RDS na MySQL/EC2, ale nejprve ho musíme nechat dohnat.

Když slave doběhne, musíme provést přerušení. Abychom to zautomatizovali, rozhodli jsme se připravit krátký bash skript, který se připojí k ProxySQL a udělá, co je třeba udělat.

# At first, we define old and new masters
OldMaster=rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com
NewMaster=172.30.4.238

(
# We remove entries from mysql_replication_hostgroup so ProxySQL logic won’t interfere
# with our script

echo "DELETE FROM mysql_replication_hostgroups;"

# Then we set current master to OFFLINE_SOFT - this will allow current transactions to
# complete while not accepting any more transactions - they will wait (by default for 
# 10 seconds) for a master to become available again.

echo "UPDATE mysql_servers SET STATUS='OFFLINE_SOFT' WHERE hostname=\"$OldMaster\";"
echo "LOAD MYSQL SERVERS TO RUNTIME;"
) | mysql -u admin -padmin -h 127.0.0.1 -P6032


# Here we are going to check for connections in the pool which are still used by 
# transactions which haven’t closed so far. If we see that neither hostgroup 10 nor
# hostgroup 20 has open transactions, we can perform a switchover.

CONNUSED=`mysql -h 127.0.0.1 -P6032 -uadmin -padmin -e 'SELECT IFNULL(SUM(ConnUsed),0) FROM stats_mysql_connection_pool WHERE status="OFFLINE_SOFT" AND (hostgroup=10 OR hostgroup=20)' -B -N 2> /dev/null`
TRIES=0
while [ $CONNUSED -ne 0 -a $TRIES -ne 20 ]
do
  CONNUSED=`mysql -h 127.0.0.1 -P6032 -uadmin -padmin -e 'SELECT IFNULL(SUM(ConnUsed),0) FROM stats_mysql_connection_pool WHERE status="OFFLINE_SOFT" AND (hostgroup=10 OR hostgroup=20)' -B -N 2> /dev/null`
  TRIES=$(($TRIES+1))
  if [ $CONNUSED -ne "0" ]; then
    sleep 0.05
  fi
done

# Here is our switchover logic - we basically exchange hostgroups for RDS and EC2
# instance. We also configure back mysql_replication_hostgroups table.

(
echo "UPDATE mysql_servers SET STATUS='ONLINE', hostgroup_id=110 WHERE hostname=\"$OldMaster\" AND hostgroup_id=10;"
echo "UPDATE mysql_servers SET STATUS='ONLINE', hostgroup_id=120 WHERE hostname=\"$OldMaster\" AND hostgroup_id=20;"
echo "UPDATE mysql_servers SET hostgroup_id=10 WHERE hostname=\"$NewMaster\" AND hostgroup_id=110;"
echo "UPDATE mysql_servers SET hostgroup_id=20 WHERE hostname=\"$NewMaster\" AND hostgroup_id=120;"
echo "INSERT INTO mysql_replication_hostgroups VALUES (10, 20, 'hostgroups');"
echo "LOAD MYSQL SERVERS TO RUNTIME;"
) | mysql -u admin -padmin -h 127.0.0.1 -P6032

Když je vše hotovo, měli byste v tabulce mysql_servers vidět následující obsah:

mysql> select * from mysql_servers;
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| hostgroup_id | hostname                                      | port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment     |
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| 20           | 172.30.4.238                                  | 3306 | ONLINE | 1      | 0           | 100             | 10                  | 0       | 0              | read server |
| 10           | 172.30.4.238                                  | 3306 | ONLINE | 1      | 0           | 100             | 10                  | 0       | 0              | read server |
| 120          | rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com | 3306 | ONLINE | 1      | 0           | 100             | 10                  | 0       | 0              |             |
| 110          | rds2.cvsw8xpajw2b.us-east-1.rds.amazonaws.com | 3306 | ONLINE | 1      | 0           | 100             | 10                  | 0       | 0              |             |
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+

Na straně aplikace byste neměli zaznamenat velký dopad, díky schopnosti ProxySQL řadit dotazy do fronty po nějakou dobu.

Tímto jsme dokončili proces přesunu vaší databáze z RDS do EC2. Posledním krokem, který je třeba udělat, je odstranit našeho RDS slave – odvedl svou práci a lze jej smazat.

V našem příštím příspěvku na blogu na tom budeme stavět. Projdeme si scénář, ve kterém přesuneme naši databázi z AWS/EC2 do samostatného poskytovatele hostingu.


  1. Jak přidat indikátor Meridiem (AM/PM) k časové hodnotě v Oracle

  2. Přidejte sloupec, který představuje zřetězení dvou dalších sloupců Varchar

  3. Jak dekódovat hex bajtového sloupce PostgreSQL na int16/uint16 v r?

  4. Způsoby, jak vědět, jak se vypořádat s korupcí databáze na serveru SQL