1 MySql主从复制简介
1.1 主从复制的概念
MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。
1.2 主从复制的作用
数据的热备:作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
架构的扩展:业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
读写分离:使数据库能支撑更大的并发。
(1)在从服务器可以执行查询工作(即我们常说的读功能),降低主服务器压力;(主库写,从库读,降压)
(2)在从服务器进行备份,避免备份期间影响主服务器服务;(确保数据安全)
高可用性:数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,也就是当服务器出现故障或宕机的情况下,可以切换到从服务器上,保证服务的正常运行。
2. 搭建主从复制
2.1 pull mysql 镜像
docker pull mysql
2.2 新建主服务器容器实例 3307
先创建文件夹: mkdir -p /mydocker/mysql-master/log mkdir -p /mydocker/mysql-master/data mkdir -p /mydocker/mysql-master/conf docker run -p 3307:3306 --name=mysql-master -v /mydocker/mysql-master/log:/var/log/mysql -v /mydocker/mysql-master/data:/var/lib/mysql -v /mydocker/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql [root@192 mysql-master]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6a298c5defda mysql "docker-entrypoint.s…" 4 seconds ago Up 2 seconds 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp mysql-master
#创建容器时出现 找不着/var/lib/mysql-files 的错误
解决办法:在my.cnf 配置文件中加入 secure_file_priv=/var/lib/mysql
2.2.1 master创建 my.cnf
在/mydocker/mysql-master/conf 目录下 创建 my.cnf
[mysqld] #指定此路径限制数据导入导出,不然默认读取/var/lib/mysql-files路径,但是容器中此路径没有会报错 secure_file_priv=/var/lib/mysql #设置server_id,同一局域网中需要唯一 server_id=101 #指定不需要同步的数据库名称 binlog-ignore-db=mysql #开启二进制日志功能 log-bin=mall-mysql-bin #设置二进制日志使用内存大小(事务) binlog_cache_size=1M #设置使用的二进制日志格式(mixed,statement,row) binlog_format=mixed #二进制日志过期清理时间,默认值为0,表示不自动清理 expire_logs_days=7 #跳过主从复制中遇到的所有错误或指定类型的错误,避免slae端复制终端 #如:1062错误是指一些主键重复,1032错误是因为主从数据库不一致 slave_skip_errors=1062
2.2.2 重启master
docker restart 6a298c5defda
2.2.3 进入mysql 容器,创建同步用户
docker exec -it mysql-master /bin/bash mysql -uroot -p mysql> CREATE USER 'slave'@'%'IDENTIFIED BY '123456'; Query OK, 0 rows affected (0.15 sec) mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON*.*TO'slave'@'%'; Query OK, 0 rows affected (0.01 sec)
#由于mysql8之后默认使用认证方式为caching_sha2_password,会使主从复制change命令后出现Slave_IO_Running: Connecting
解决办法:
① :在my.cnf 配置文件中加入 default_authentication_plugin=mysql_native_password
② :在master mysql中执行 ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
2.3 新建从服务器容器实例 3308
[root@192 ~]# docker run -p 3308:3306 --name=mysql-slave -v /mydocker/mysql-slave/log:/var/log/mysql -v /mydocker/mysql-slave/data:/var/lib/mysql -v /mydocker/mysql-slave/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql [root@192 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d284702c6992 mysql "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 33060/tcp, 0.0.0.0:3308->3306/tcp, :::3308->3306/tcp mysql-slave 7b510affe5f3 mysql "docker-entrypoint.s…" 12 minutes ago Up 12 minutes 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp mysql-master [root@192 ~]#
#创建容器时出现 找不着/var/lib/mysql-files 的错误
解决办法:在my.cnf 配置文件中加入 secure_file_priv=/var/lib/mysql
2.3.1 slave创建 my.cnf
[mysqld] #指定此路径限制数据导入导出,不然默认读取/var/lib/mysql-files路径,但是容器中此路径没有会报错 secure_file_priv=/var/lib/mysql #设置server_id,同一局域网中需要唯一 server_id=102 #指定不需要同步的数据库名称 binlog-ignore-db=mysql #开始二进制日志功能,以备slave作为其他数据库实例的Master时使用 log-bin=mall-mysql-slave1-bin #设置二进制使用内存大小 (事务) binlog_cache_size=1M #设置使用二进制日期格式 binlog_format=mixed #二进制日志过期清理时间。默认为0,表示不自动清理 expire_logs_days=7 #跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制终端。 #如 1062错误是指一些主键重复,1032错误是因为主从数据库不一致 slave_skip_errors=1062 #relay_log 配置中继日志 relay_log=mall-mysql-relay-bin #表示slave将复制事件写进自己的二进制日志 log_slave_updates=1 #slave设置为只读(具有super权限的用户除外) read_only=1
2.3.2 重启slave 实例
docker restart mysql-slave docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d284702c6992 mysql "docker-entrypoint.s…" 12 hours ago Up 5 minutes 33060/tcp, 0.0.0.0:3308->3306/tcp, :::3308->3306/tcp mysql-slave 7b510affe5f3 mysql "docker-entrypoint.s…" 12 hours ago Up 7 seconds 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp mysql-master
2.3.3 在master中查看主从同步状态
mysql> show master status; +-----------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-----------------------+----------+--------------+------------------+-------------------+ | mall-mysql-bin.000006 | 156 | | mysql | | +-----------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.02 sec)
2.3.4 在从数据库中配置主从复制
mysql> change master to master_host='192.168.217.145',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000005',master_log_pos=156,master_connect_retry=30; Query OK, 0 rows affected, 10 warnings (0.18 sec) master_host: 主数据库的ip地址 master_user: 在主数据库创建的用于同步数据的用户账号 master_password: 在主数据库创建的用于同步数据的用户密码 master_port: 主数据库的运行端口 master_log_file: 指定从数据库要复制数据的日志文件,通过查看主数据库的状态,获取File参数 master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据库的状态,获取Position master_connect_retry: 连接失败重试的时间间隔,单位为妙 mysql> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.145.217 Master_User: slave Master_Port: 3307 Connect_Retry: 30 Master_Log_File: mall-mysql-bin.000005 Read_Master_Log_Pos: 156 Relay_Log_File: mall-mysql-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mall-mysql-bin.000005 Slave_IO_Running: No Slave_SQL_Running: No 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: 156 Relay_Log_Space: 156 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: NULL 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: 0 Master_UUID: Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: 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: Master_public_key_path: Get_master_public_key: 0 Network_Namespace: 1 row in set, 1 warning (0.03 sec)
2.3.5 在从数据中开启主从同步
mysql> start slave;
2.3.6 再次查看 slave status
mysql> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 192.168.217.145 Master_User: slave Master_Port: 3307 Connect_Retry: 30 Master_Log_File: mall-mysql-bin.000007 Read_Master_Log_Pos: 156 Relay_Log_File: mall-mysql-relay-bin.000002 Relay_Log_Pos: 329 Relay_Master_Log_File: mall-mysql-bin.000007 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: 156 Relay_Log_Space: 543 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: 0 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: 101 Master_UUID: 4d815ecc-e845-11ee-aad4-0242ac110003 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates 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: Master_public_key_path: Get_master_public_key: 0 Network_Namespace: 1 row in set, 1 warning (0.00 sec)
下面2项的状态已经由No 变成 Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
3 主从复制测试
3.1主机添加数据
mysql> create database db01; Query OK, 1 row affected (0.11 sec) mysql> use db01; Database changed mysql> create table t1(id int,name varchar(20)); Query OK, 0 rows affected (1.94 sec) mysql> insert t1 values(1,'z3'); Query OK, 1 row affected (0.01 sec)
3.2 从机直接使用
mysql> use db01; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from t1; +------+------+ | id | name | +------+------+ | 1 | z3 | +------+------+ 1 row in set (0.00 sec)