sql >> Database teknologi >  >> RDS >> Mysql

MySQL i skyen - Online migration fra Amazon RDS til din egen server:Del 2

Som vi så tidligere, kan det være en udfordring for virksomheder at flytte deres data ud af RDS til MySQL. I den første del af denne blog viste vi dig, hvordan du opsætter dit målmiljø på EC2 og indsætter et proxy-lag (ProxySQL) mellem dine applikationer og RDS. I denne anden del viser vi dig, hvordan du foretager selve migreringen af ​​data til din egen server og derefter omdirigerer dine applikationer til den nye databaseinstans uden nedetid.

Kopierer data ud af RDS

Når vi har vores databasetrafik kørende gennem ProxySQL, kan vi begynde forberedelserne til at kopiere vores data ud af RDS. Vi skal gøre dette for at opsætte replikering mellem RDS og vores MySQL-instans, der kører på EC2. Når dette er gjort, konfigurerer vi ProxySQL til at omdirigere trafik fra RDS til vores MySQL/EC2.

Som vi diskuterede i det første blogindlæg i denne serie, er den eneste måde, du kan få data ud af RDS på, via logisk dump. Uden adgang til instansen kan vi ikke bruge nogle varme, fysiske backupværktøjer som xtrabackup. Vi kan heller ikke bruge snapshots, da der ikke er nogen måde at bygge noget andet end en ny RDS-instans fra snapshotet.

Vi er begrænset til logiske dump-værktøjer, derfor ville den logiske mulighed være at bruge mydumper/myloader til at behandle dataene. Heldigvis kan mydumper oprette konsekvente sikkerhedskopier, så vi kan stole på, at den leverer binlog-koordinater, som vores nye slave kan oprette forbindelse til. Hovedproblemet ved opbygning af RDS-replikaer er binlog-rotationspolitik - logisk dump og indlæsning kan tage endda dage på større (hundredvis af gigabyte) datasæt og du skal opbevare binlogs på RDS-instansen i hele denne proces. Selvfølgelig kan du øge binlog-rotationsretentionen på RDS (kald mysql.rds_set_configuration('binlog retention hours', 24); - du kan beholde dem i op til 7 dage), men det er meget sikrere at gøre det anderledes.

Før vi fortsætter med at tage et dump, tilføjer vi en replika til vores RDS-instans.

Amazon RDS Dashboard Opret replika DB i RDS

Når vi klikker på knappen "Opret læst replika", vil et øjebliksbillede blive startet på "master" RDS-replikaen. Det vil blive brugt til at klargøre den nye slave. Processen kan tage timer, det hele afhænger af volumenstørrelsen, hvornår der sidst blev taget et snapshot og lydstyrkens ydeevne (io1/gp2? Magnetisk? Hvor mange pIOPS har en volumen?).

Master RDS Replica

Når slaven er klar (dens status er ændret til "tilgængelig"), kan vi logge ind på den ved hjælp af dens RDS-endepunkt.

RDS-slave

Når vi er logget ind, stopper vi replikering på vores slave - dette vil sikre, at RDS-masteren ikke renser binære logfiler, og de vil stadig være tilgængelige for vores EC2-slave, når vi har afsluttet vores dump-/genindlæsningsproces.

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)

Nu er det endelig tid til at kopiere data til EC2. Først skal vi installere mydumper. Du kan få det fra github:https://github.com/maxbube/mydumper. Installationsprocessen er ret enkel og pænt beskrevet i readme-filen, så vi vil ikke dække det her. Mest sandsynligt bliver du nødt til at installere et par pakker (angivet i readme), og den sværeste del er at identificere, hvilken pakke der indeholder mysql_config - det afhænger af MySQL-smag (og nogle gange også MySQL-version).

Når du har kompileret mydumper og klar til at gå, kan du udføre den:

[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
. 

Bemærk venligst --lock-all-tables, som sikrer, at øjebliksbilledet af dataene vil være konsistent, og det vil være muligt at bruge det til at oprette en slave. Nu må vi vente, indtil mydumper fuldfører sin opgave.

Et trin mere er påkrævet - vi ønsker ikke at gendanne mysql-skemaet, men vi skal kopiere brugere og deres bevillinger. Vi kan bruge pt-show-grants til det:

[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

Eksempel på pt-show-grants kan se sådan ud:

-- 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'@'%';

Det er op til dig at vælge, hvilke brugere der skal kopieres til din MySQL/EC2-instans. Det giver ikke mening at gøre det for dem alle. For eksempel har root-brugere ikke 'SUPER'-privilegium på RDS, så det er bedre at genskabe dem fra bunden. Det du skal kopiere er tilskud til din applikationsbruger. Vi skal også kopiere brugere, der bruges af ProxySQL (proxysql-monitor i vores tilfælde).

Indsættelse af data i din MySQL/EC2-instans

Som nævnt ovenfor ønsker vi ikke at gendanne systemskemaer. Derfor flytter vi filer relateret til disse skemaer ud af vores mydumper-mappe:

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

Når vi er færdige med det, er det tid til at begynde at indlæse data i MySQL/EC2-instansen:

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

Bemærk venligst, at vi brugte fire tråde (-t 4) - sørg for at indstille dette til det, der giver mening i dit miljø. Det handler om at mætte mål-MySQL-instansen - enten CPU eller I/O, afhængigt af flaskehalsen. Vi ønsker at presse så meget ud af det som muligt for at sikre, at vi brugte alle tilgængelige ressourcer til at indlæse dataene.

Efter at hoveddataene er indlæst, er der yderligere to trin at tage, begge er relateret til RDS-internal, og begge kan ødelægge vores replikering. For det første indeholder RDS et par rds_*-tabeller i mysql-skemaet. Vi vil gerne indlæse dem, hvis nogle af dem bliver brugt af RDS - replikering vil bryde, hvis vores slave ikke vil have dem. Vi kan gøre det på følgende måde:

[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

Lignende problem er med tidszonetabeller, vi skal indlæse dem ved hjælp af data fra RDS-instansen:

[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

Når alt dette er klart, kan vi konfigurere replikering mellem RDS (master) og vores MySQL/EC2-instans (slave).

Opsætning af replikering

Når Mydumper udfører en konsekvent dump, skriver den en binær logposition ned. Vi kan finde disse data i en fil kaldet metadata i dump-mappen. Lad os tage et kig på det, så vil vi bruge positionen til at opsætte replikering.

[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

En sidste ting, vi mangler, er en bruger, som vi kunne bruge til at opsætte vores slave. Lad os oprette en på RDS-instansen:

[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)

Nu er det tid til at slave vores MySQL/EC2-server fra RDS-instansen:

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)

Sidste trin vil være at skifte vores trafik fra RDS-instansen til MySQL/EC2, men vi er nødt til at lade den indhente det først.

Når slaven har indhentet, skal vi udføre en cutover. For at automatisere det besluttede vi at forberede et kort bash-script, som vil forbinde til ProxySQL og gøre det, der skal gøres.

# 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

Når alt er gjort, bør du se følgende indhold i mysql_servers-tabellen:

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              |             |
+--------------+-----------------------------------------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+

På applikationssiden burde du ikke se meget af en effekt, takket være ProxySQL's evne til at stille forespørgsler i kø i nogen tid.

Hermed afsluttede vi processen med at flytte din database fra RDS til EC2. Sidste skridt at gøre er at fjerne vores RDS-slave - den gjorde sit arbejde, og den kan slettes.

I vores næste blogindlæg vil vi bygge videre på det. Vi vil gennemgå et scenarie, hvor vi flytter vores database ud af AWS/EC2 til en separat hostingudbyder.


  1. En oversigt over de forskellige scanningsmetoder i PostgreSQL

  2. 9 bedste fremgangsmåder til at skrive SQL-forespørgsler

  3. Sådan installeres phpMyAdmin på administrerede hostingkonti

  4. Sådan installeres Oracle Express Edition til SQL Practice