基本流程

docker-compose.yml文件配置
#数据库-主库
mysql57:
image: ${MYSQL_IMAGE}
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_MASTER_ROOT_PASSWORD}
#- MYSQL_USER=user
#- MYSQL_PASSWORD=password
volumes:
#配置文件
- ${MYSQL_MASTER_CONF}:/etc/mysql/my.cnf:ro
#数据目录
- ${MYSQL_MASTER_DATA}:/var/lib/mysql/:rw
#查询日志文件
#- ./logs/mysql/query_mysql.log:/var/logs/mysql/query.mysql.log:rw
#慢查询日志文件
#- ./logs/mysql/slow_mysql.log:/var/logs/mysql/slow.mysql.log:rw
restart: always
ports:
- "${MYSQL_MASTER_PORT}:3306"
container_name: mysql57
#从库01
mysql57-slave01:
depends_on:
- mysql57
image: ${MYSQL_IMAGE}
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_SLAVE_01_ROOT_PASSWORD}
- MASTER_HOST=mysql57
#- MYSQL_USER=user
#- MYSQL_PASSWORD=password
volumes:
#配置文件
- ${MYSQL_SLAVE_01_CONF}:/etc/mysql/my.cnf:ro
#数据目录
- ${MYSQL_SLAVE_01_DATA}:/var/lib/mysql/:rw
#查询日志文件
#- ./logs/mysql/query_mysql.log:/var/logs/mysql/query.mysql.log:rw
#慢查询日志文件
#- ./logs/mysql/slow_mysql.log:/var/logs/mysql/slow.mysql.log:rw
restart: always
ports:
- "${MYSQL_SLAVE_01_PORT}:3306"
container_name: mysql57-slave01
#从库02
mysql57-slave02:
depends_on:
- mysql57
image: ${MYSQL_IMAGE}
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_SLAVE_02_ROOT_PASSWORD}
- MASTER_HOST=mysql57
#- MYSQL_USER=user
#- MYSQL_PASSWORD=password
volumes:
#配置文件
- ${MYSQL_SLAVE_02_CONF}:/etc/mysql/my.cnf:ro
#数据目录
- ${MYSQL_SLAVE_02_DATA}:/var/lib/mysql/:rw
#查询日志文件
#- ./logs/mysql/query_mysql.log:/var/logs/mysql/query.mysql.log:rw
#慢查询日志文件
#- ./logs/mysql/slow_mysql.log:/var/logs/mysql/slow.mysql.log:rw
restart: always
ports:
- "${MYSQL_SLAVE_02_PORT}:3306"
container_name: mysql57-slave02master配置
my.cnf文件加入:
## 设置server_id,一般设置为IP,同一局域网内注意要唯一
server_id=id1
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 开启二进制日志功能,可以随便取,最好有含义(关键就是这里了)
log-bin=community-mysql-bin
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062重启master
service mysql restart
查看master状态
mysql> show master status \G;得到类似:
*************************** 1. row ***************************
File: community-mysql-bin.000003
Position: 50759
Binlog_Do_DB:
Binlog_Ignore_DB: mysql
Executed_Gtid_Set:
1 row in set (0.00 sec)master库创建slave用户
CREATE USER 'slave01'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave01'@'%';
CREATE USER 'slave02'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave02'@'%';slave配置
my.cnf文件加入:
## 设置server_id,唯一
server_id=id2
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=community-mysql-slave-bin
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=community-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## 防止改变数据(除了特殊的线程)
read_only=1重启slave
service mysql restart
查看slave状态
show slave status \G;
连接master服务器
-- 两个从库分别配置主库
change master to master_host='mysql57',master_user='slave01',master_password='password',master_port=port,master_log_file='master库的master_log_file文件:上面通过`show master status`得到的File字段',master_log_pos=0;
change master to master_host='mysql57',master_user='slave02',master_password='password',master_port=port,master_log_file='master库的master_log_file文件:上面通过`show master status`得到的File字段',master_log_pos=0;
-- 开启同步
start slave;
-- 查看状态
show slave status \G;显示类似内容:
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql57
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: community-mysql-bin.000003
Read_Master_Log_Pos: 51273
Relay_Log_File: community-mysql-relay-bin.000002
Relay_Log_Pos: 51506
Relay_Master_Log_File: community-mysql-bin.000003
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: 51273
Relay_Log_Space: 51723
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: 100
Master_UUID: 9d09b11c-fdeb-11e8-8ac4-0242ac140006
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave 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:
1 row in set (0.00 sec)如果Slave_IO_Running,Slave_SQL_Running不为YES,则排查以上步骤是否正确
至此配置完成
laravel中相关配置
在config/database.php中mysql段配置如下:
'mysql' => [
'read' => [
'host' => env('DB_SLAVE_HOST', '127.0.0.1'),
],
'write' => [
'host' => env('DB_HOST', '127.0.0.1'),
],
'sticky' => true,
'driver' => 'mysql',
'database' => env('DB_DATABASE', ''),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
],注意
- 如果是线上操作(持续有数据写入),则需要按照以下步骤:master锁表-->master备份数据-->master解锁表 -->slave导入数据-->slave设置主从-->查看主从
- 如果多个从库需要注意
- 数据目录
auto.cnf中的server-uuid唯一 - 配置文件
my.cnf中的server_id唯一
- 数据目录
- 需要在从库的容器环境变量中添加
MASTER_HOST=主节点容器名称来确保容器重启之后自动同步主库binlog
错误修复
如果遇到类似以下错误,可能是由于主从库之间结构不同或其他原因造成的SQL query执行失败
mysql> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 1.2.3.4
Master_User: slave_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.001079
Read_Master_Log_Pos: 269214454
Relay_Log_File: slave-relay.000130
Relay_Log_Pos: 100125935
Relay_Master_Log_File: mysql-bin.001079
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB: mydb
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1146
Last_Error: Error 'Table 'mydb.taggregate_temp_1212047760' doesn't exist' on query. Default database: 'mydb'.
Query: 'UPDATE thread AS thread,taggregate_temp_1212047760 AS aggregate
SET thread.views = thread.views + aggregate.views
WHERE thread.threadid = aggregate.threadid'
Skip_Counter: 0
Exec_Master_Log_Pos: 203015142
Relay_Log_Space: 166325247
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
1 row in set (0.00 sec)可以通过以下步骤跳过错误
mysql> stop slave;-- 停止
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;-- 跳过指定数量的SQL query,此处为1条
mysql> start slave;-- 开启
mysql> show slave status \G;-- 状态
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql57
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: community-mysql-bin.000005
Read_Master_Log_Pos: 2145
Relay_Log_File: community-mysql-relay-bin.000010
Relay_Log_Pos: 330
Relay_Master_Log_File: community-mysql-bin.000005
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: 2145
Relay_Log_Space: 2771
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: 100
Master_UUID: c28b993e-368d-11e9-96c4-0242ac120002
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave 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:
1 row in set (0.00 sec)
ERROR:
No query specified