1.为什么要复制数据库?

  1. 读写分离
    通过MySQL复制可以实现读写分离,将读操作分布到多个不同的服务器上,减轻服务器的压力。
    2. 备份
    从库可以作为数据的异地实时备份。
    3. 故障切换
    当主库遇到故障,系统可以切换到从库,实现故障切换。
    4. 升级测试
    从库可作为测试服务器的数据库。

2.复制数据的步骤:

  1. 在主库上把数据更改记录到二进制日志(Binary Log)中。
  2. 备库将主库上的日志复制到自己的中继日志(Relay Log)中。
  3. 备库读取中继日志中的事件,将其在备库上重新执行一遍。

在两台机器分别启动 MySQL 实例, MySQL 搭建方式可以参考

IP 系统 端口 MySQL版本 节点
192.168.88.222 Centos7.4 3306 5.7.20 Master
192.168.88.61 Centos7.4 3306 5.7.20 Salve

关键配置:
Master:

  1. [client]
  2. port = 3306
  3. default-character-set=utf8mb4
  4. socket = /data/mysql_db/mysql_seg_3306/mysql.sock
  5. [mysqld]
  6. datadir = /data/mysql_db/mysql_seg_3306
  7. basedir = /usr/local/mysql57
  8. tmpdir = /tmp
  9. socket = /data/mysql_db/mysql_seg_3306/mysql.sock
  10. pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid
  11. skip-external-locking = 1
  12. skip-name-resolve = 1
  13. port = 3306
  14. server_id = 222
  15. default-storage-engine = InnoDB
  16. character-set-server = utf8mb4
  17. default_password_lifetime=0
  18. #### log ####
  19. log_timestamps=system
  20. log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin
  21. log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index
  22. binlog_format = row
  23. relay_log_recovery=ON
  24. relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin
  25. relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index
  26. log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log
  27. #### replication ####
  28. replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.%
  29. #### semi sync replication settings #####
  30. plugin_dir=/usr/local/mysql57/lib/plugin
  31. plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
  32. loose_rpl_semi_sync_master_enabled = 1
  33. loose_rpl_semi_sync_slave_enabled = 1
  34. loose_rpl_semi_sync_master_timeout = 5000

Salve

  1. [client]
  2. port = 3306
  3. default-character-set=utf8mb4
  4. socket = /data/mysql_db/mysql_seg_3306/mysql.sock
  5. [mysqld]
  6. datadir = /data/mysql_db/mysql_seg_3306
  7. basedir = /usr/local/mysql57
  8. tmpdir = /tmp
  9. socket = /data/mysql_db/mysql_seg_3306/mysql.sock
  10. pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid
  11. skip-external-locking = 1
  12. skip-name-resolve = 1
  13. port = 3306
  14. server_id = 61
  15. read_only=1
  16. default-storage-engine = InnoDB
  17. character-set-server = utf8mb4
  18. default_password_lifetime=0
  19. #### log ####
  20. log_timestamps=system
  21. log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin
  22. log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index
  23. binlog_format = row
  24. relay_log_recovery=ON
  25. relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin
  26. relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index
  27. log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log
  28. #### replication ####
  29. replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.%
  30. #### semi sync replication settings #####
  31. plugin_dir=/usr/local/mysql57/lib/plugin
  32. plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
  33. loose_rpl_semi_sync_master_enabled = 1
  34. loose_rpl_semi_sync_slave_enabled = 1
  35. loose_rpl_semi_sync_master_timeout = 5000

配置解析

3.搭建主从

现在我们的环境如下

  • 192.168.88.61:3306 Master 节点,正在使用
  • 192.168.88.222:3306 新搭建数据库,要在上面做 192.168.41.83 的备库

    同步用户

    我们创建一个用户名为 repl 的用户,授予 REPLICATION SLAVE 权限专门用来同步

    1. db83-3306>>CREATE USER 'repl'@'%' IDENTIFIED BY 'repl';
    2. Query OK, 0 rows affected (5.01 sec)
    3. db83-3306>>GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
    4. Query OK, 0 rows affected (0.00 sec)
    5. db83-3306>>flush privileges;
    6. Query OK, 0 rows affected (0.00 sec)

    开启同步

    回到备份文件,我们从头部找到 Master 备份时间点的二进制日志位置

    1. [mysql@mysql-test-72 ~]$ head -30 mysql_backup_full.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE'
    2. -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=154;

    MASTER_LOG_FILEMASTER_LOG_POS 就是在 Master 执行 show master status 得到的二进制位置信息。现在,我们执行同步命令

    1. -- 重置复制
    2. -- reset slave;
    3. -- 同步配置
    4. CHANGE MASTER TO
    5. MASTER_HOST='192.168.41.83',
    6. MASTER_PORT=3306,
    7. MASTER_USER='repl',
    8. MASTER_PASSWORD='repl',
    9. MASTER_LOG_FILE='mysql-bin.000004',
    10. MASTER_LOG_POS=154;
    11. -- 开启同步
    12. start slave

    实际执行结果如下

    1. db72-3306>>CHANGE MASTER TO
    2. -> MASTER_HOST='192.168.41.83',
    3. -> MASTER_PORT=3306,
    4. -> MASTER_USER='repl',
    5. -> MASTER_PASSWORD='repl',
    6. -> MASTER_LOG_FILE='mysql-bin.000004',
    7. -> MASTER_LOG_POS=154;
    8. Query OK, 0 rows affected, 2 warnings (0.20 sec)
    9. db72-3306>>start slave;
    10. Query OK, 0 rows affected (0.01 sec)

    查看同步状态

    1. db72-3306>>show slave status \G;
    2. *************************** 1. row ***************************
    3. Slave_IO_State: Waiting for master to send event
    4. Master_Host: 192.168.41.83
    5. Master_User: repl
    6. Master_Port: 3306
    7. Connect_Retry: 60
    8. Master_Log_File: mysql-bin.000004
    9. Read_Master_Log_Pos: 154
    10. Relay_Log_File: mysql-relay-bin.000002
    11. Relay_Log_Pos: 320
    12. Relay_Master_Log_File: mysql-bin.000004
    13. Slave_IO_Running: Yes
    14. Slave_SQL_Running: Yes
    15. Replicate_Do_DB:
    16. Replicate_Ignore_DB:
    17. Replicate_Do_Table:
    18. Replicate_Ignore_Table:
    19. Replicate_Wild_Do_Table:
    20. Replicate_Wild_Ignore_Table:
    21. Last_Errno: 0
    22. Last_Error:
    23. Skip_Counter: 0
    24. Exec_Master_Log_Pos: 154
    25. Relay_Log_Space: 527
    26. Until_Condition: None
    27. Until_Log_File:
    28. Until_Log_Pos: 0
    29. Master_SSL_Allowed: No
    30. Master_SSL_CA_File:
    31. Master_SSL_CA_Path:
    32. Master_SSL_Cert:
    33. Master_SSL_Cipher:
    34. Master_SSL_Key:
    35. Seconds_Behind_Master: 0
    36. Master_SSL_Verify_Server_Cert: No
    37. Last_IO_Errno: 0
    38. Last_IO_Error:
    39. Last_SQL_Errno: 0
    40. Last_SQL_Error:
    41. Replicate_Ignore_Server_Ids:
    42. Master_Server_Id: 833306
    43. Master_UUID: 15958368-e9a0-11e8-a98c-ecb1d77febe4
    44. Master_Info_File: /data/mysql_db/mysql_seg_3306/master.info
    45. SQL_Delay: 0
    46. SQL_Remaining_Delay: NULL
    47. Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
    48. Master_Retry_Count: 86400
    49. Master_Bind:
    50. Last_IO_Error_Timestamp:
    51. Last_SQL_Error_Timestamp:
    52. Master_SSL_Crl:
    53. Master_SSL_Crlpath:
    54. Retrieved_Gtid_Set:
    55. Executed_Gtid_Set:
    56. Auto_Position: 0
    57. Replicate_Rewrite_DB:
    58. Channel_Name:
    59. Master_TLS_Version:
    60. 1 row in set (0.00 sec)
    61. ERROR:
    62. No query specified

    我们可以从 Slave_IO_Running, Slave_SQL_Running, Seconds_Behind_Master 这三个参数可以判断出同步状态是否正常

  • Slave_IO_Running 取 Master 日志的线程, Yes 为正在运行

  • Slave_SQL_Running 从日志恢复数据的线程, Yes 为正在运行
  • Seconds_Behind_Master 当前数据库相对于主库的数据延迟, 这个值是根据二进制日志的时间戳计算得到的(秒)