相信mysql的binlog都不陌生binlog的主要作用就是进行数据同步,今天我们从数据同步的角度搭一下mysql的主从/双主。
base
以下基于mysql5.7
简单了解下binlog
binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。
binlog日志包括两类文件:二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句)语句事件。
binlog有三种格式:statement基于sql语句复制、row基于行数据变更的复制、mixed混合前两种格式的复制。
搭建主从结构
创建docker-compose
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| version: '3.8' services: mysql-master: container_name: mysql-master image: mysql:5.7.31 restart: always ports: - 13306:3306 privileged: true volumes: - $PWD/master/conf/my.cnf:/etc/mysql/my.cnf environment: MYSQL_ROOT_PASSWORD: "123456" command: [ '--character-set-server=utf8mb4', '--collation-server=utf8mb4_general_ci', '--max_connections=3000' ] networks: - myweb mysql-slave: container_name: mysql-slave image: mysql:5.7.31 restart: always ports: - 23306:3306 privileged: true volumes: - $PWD/slave/conf/my.cnf:/etc/mysql/my.cnf environment: MYSQL_ROOT_PASSWORD: "123456" command: [ '--character-set-server=utf8mb4', '--collation-server=utf8mb4_general_ci', '--max_connections=3000' ] networks: - myweb
networks: myweb: driver: bridge
|
创建配置文件
配置文件目录结构
| [root@xxx MySQLM-S] . ├── docker-compose.yaml ├── master │ └── conf │ └── my.cnf └── slave └── conf └── my.cnf
|
master/conf/my.cnf 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| [mysqld]
server-id=1
log-bin=mysql-bin
binlog-ignore-db=mysql
sync_binlog = 1
slave-skip-errors = all
|
slave/conf/my.cnf 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| [mysqld]
server-id=2
log-bin=mysql-bin
binlog-ignore-db=mysql
slave-skip-errors = all
|
启动docker-compose并配置主从关系
启动
进入master配置同步账号和权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| docker-compose exec mysql-slave bash
mysql -uroot -p123455
mysql> show variables like '%server_id%'; +----------------+-------+ | Variable_name | Value | +----------------+-------+ | server_id | 1 | | server_id_bits | 32 | +----------------+-------+
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000004 | 154 | | mysql | | +------------------+----------+--------------+------------------+-------------------+
mysql> grant replication slave,replication client on *.* to 'slave'@'%' identified by "123456"; mysql> flush privileges;
|
进入slave服务配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| docker-compose exec docker-slave bash
mysql -uroot -p123456
mysql> show variables like '%server_id%'; +----------------+-------+ | Variable_name | Value | +----------------+-------+ | server_id | 2 | | server_id_bits | 32 | +----------------+-------+
mysql> change master to master_host='mysql-master',master_user='slave',master_password='123456',master_port=3306,master_log_file='mysql-bin.000004', master_log_pos=154,master_connect_retry=30;
mysql> start slave;
mysql> show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: mysql-master Master_User: slave Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 778 Relay_Log_File: af5556aff9be-relay-bin.000002 Relay_Log_Pos: 944 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: mysql 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: 778 Relay_Log_Space: 1158 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: 1 Master_UUID: 466c4a60-03f4-11ec-a1a1-0242ac160002 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:
|
上面看到 Slave_IO_Running: Yes,Slave_SQL_Running: Yes 表示已经成功开启主从
连接主mysql参数说明:
master_port:Master的端口号,指的是容器的端口号
master_user:用于数据同步的用户
master_password:用于同步的用户的密码
master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
搭建双主结构
通过上面主从结构我们可以我们可以大胆设想,要是两个数据库的实例都配置对方为master不就实现的双主么?事实却是如此:
双主结构只需要将双方的配置文件注释掉的地方取消注释掉分别在两台服务器上创同步账号和配置
创建docker-compose文件(双主)
这里只更改了docker-compose中服务的名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| version: '3.8' services: mysql-m1: container_name: mysql-m1 image: mysql:5.7.31 restart: always ports: - 13306:3306 privileged: true volumes: - $PWD/m1/conf/my.cnf:/etc/mysql/my.cnf environment: MYSQL_ROOT_PASSWORD: "123456" command: [ '--character-set-server=utf8mb4', '--collation-server=utf8mb4_general_ci', '--max_connections=3000' ] networks: - myweb mysql-m2: container_name: mysql-m2 image: mysql:5.7.31 restart: always ports: - 23306:3306 privileged: true volumes: - $PWD/m2/conf/my.cnf:/etc/mysql/my.cnf environment: MYSQL_ROOT_PASSWORD: "123456" command: [ '--character-set-server=utf8mb4', '--collation-server=utf8mb4_general_ci', '--max_connections=3000' ] networks: - myweb
networks: myweb: driver: bridge
|
创建配置文件(双主)
这里只是将主从中的配置中注释掉的服务添加上
配置文件目录结构(双主)
| [root@xxx MySQLM-M] . ├── docker-compose.yaml ├── m1 │ └── conf │ └── my.cnf └── m2 └── conf └── my.cnf
|
m1/conf/my.cnf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| [mysqld]
server-id=1
log-slave-updates = true
auto_increment_offset = 1 auto_increment_increment = 2
log-bin=mysql-bin
binlog-ignore-db=mysql
sync_binlog = 1
slave-skip-errors = all
|
m2/conf/my.cnf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| [mysqld]
server-id=2
log-slave-updates = true
auto_increment_offset = 2 auto_increment_increment = 2
log-bin=mysql-bin
binlog-ignore-db=mysql
sync_binlog = 1
slave-skip-errors = all
|
启动docker-compose并配置m1和m2的双主
启动(双主)
进入m1和m2下执行下列命令来获取各自的master status 和同步账号
m1:
| docker-compose exec mysql-m1 bash
mysql -uroot -p123456
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000005 | 154 | | mysql | | +------------------+----------+--------------+------------------+-------------------+
mysql> grant replication slave,replication client on *.* to 'slave'@'%' identified by "123456"; mysql> flush privileges;
|
m2:
| docker-compose exec mysql-m1 bash
mysql -uroot -p123456
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000005 | 154 | | mysql | | +------------------+----------+--------------+------------------+-------------------+
mysql> grant replication slave,replication client on *.* to 'slave'@'%' identified by "123456"; mysql> flush privileges;
|
m1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| mysql> change master to master_host='mysql-m2',master_user='slave',master_password='123456',master_port=3306,master_log_file='mysql-bin.000005', master_log_pos=154,master_connect_retry=30;
mysql> start slave;
mysql> show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: mysql-m2 Master_User: slave Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 620 Relay_Log_File: de7a84f1b7f1-relay-bin.000002 Relay_Log_Pos: 786 Relay_Master_Log_File: 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: 620 Relay_Log_Space: 1000 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: 2 Master_UUID: de8af5ce-0410-11ec-ab6d-0242ac170003 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:
|
m2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| mysql> change master to master_host='mysql-m1',master_user='slave',master_password='123456',master_port=3306,master_log_file='mysql-bin.000005', master_log_pos=154,master_connect_retry=30;
mysql> start slave;
mysql> show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: mysql-m1 Master_User: slave Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 1086 Relay_Log_File: 65322be4d8a9-relay-bin.000002 Relay_Log_Pos: 786 Relay_Master_Log_File: 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: 1086 Relay_Log_Space: 1000 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: 1 Master_UUID: de898a82-0410-11ec-9fee-0242ac170002 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:
|
至此双主节点设置完成
总结
主从模式多用来进行读写分离
双主模式多用来进行高可用
更复杂的部署可能会部署多master和多slave并用keeplive保证统一访问的模式,这里没探究