本章是Docker 下 MySQL 主从三部曲的终篇, 前面的章节我们能够制作镜像来搭建主从同步环境, 本章我们来观察 binlog 参数 MASTER_LOG_POS;
前文链接
Docker 下 MySQL 主从三部曲之一: 极速体验;
Docker 下 MySQL 主从三部曲之二: 细说镜像制作;
关于从库同步的设置
在设置从库同步的时候一般会使用以下 SQL:
- CHANGE MASTER TO MASTER_HOST='172.17.0.2', \
- MASTER_USER='rep', \
- MASTER_PASSWORD='888888', \
- MASTER_LOG_FILE='mysql-bin.000001', \
- MASTER_LOG_POS=745;
今天我们的实战和上面的 MASTER_LOG_FILE,MASTER_LOG_POS 两个参数有关;
第一个问题
上一章制作从库镜像时并未设置 MASTER_LOG_FILE 和 MASTER_LOG_POS, 但是之前的文章Docker 下手工配置 MySQL 主从中却又设置了这两个参数, 那么在设置主从同步的时候, 究竟该不该设置这两个参数呢?
前面两章实战我们已经验证过了, 不设置这两个参数并不会影响主从同步, 所以可以不设置, 那么就剩下一个问题: 设置了 MASTER_LOG_FILE 和 MASTER_LOG_POS 有什么影响?
参数 MASTER_LOG_FILE
在 master 容器的 MySQL 命令行执行 show master status:
- mysql> show master status;
- +------------------+----------+--------------+------------------+-------------------+
- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
- +------------------+----------+--------------+------------------+-------------------+
- | mysql-bin.000003 | 154 | | | |
- +------------------+----------+--------------+------------------+-------------------+
- 1 row in set (0.00 sec)
如上所示, bin log 文件名为 mysql-bin.000003, 在 / etc/mysql/mysql.conf.d/mysqld.cnf 中定义的文件路径如下:
- [mysqld]
- pid-file = /var/run/mysqld/mysqld.pid
- socket = /var/run/mysqld/mysqld.sock
- datadir = /var/lib/mysql
- #log-error = /var/log/mysql/error.log
- # By default we only accept connections from localhost
- #bind-address = 127.0.0.1
- # Disabling symbolic-links is recommended to prevent assorted security risks
- symbolic-links=0
根据以上配置信息, 我们在 / var/lib/mysql 目录下找到了 bin log 文件 mysql-bin.000003, 如下:
- root@ae594a28192d:/var/lib/mysql# pwd
- /var/lib/mysql
- root@ae594a28192d:/var/lib/mysql# ls -al
- total 191468
- drwxr-xr-x 5 mysql mysql 4096 Apr 2 01:12 .
- drwxr-xr-x 19 root root 4096 Mar 14 07:47 ..
- -rw-r----- 1 mysql mysql 56 Apr 2 01:12 auto.cnf
- -rw------- 1 mysql mysql 1675 Apr 2 01:12 ca-key.pem
- -rw-r--r-- 1 mysql mysql 1107 Apr 2 01:12 ca.pem
- -rw-r--r-- 1 mysql mysql 1107 Apr 2 01:12 client-cert.pem
- -rw------- 1 mysql mysql 1675 Apr 2 01:12 client-key.pem
- -rw-r----- 1 mysql mysql 1353 Apr 2 01:12 ib_buffer_pool
- -rw-r----- 1 mysql mysql 50331648 Apr 2 01:13 ib_logfile0
- -rw-r----- 1 mysql mysql 50331648 Apr 2 01:12 ib_logfile1
- -rw-r----- 1 mysql mysql 79691776 Apr 2 01:13 ibdata1
- -rw-r----- 1 mysql mysql 12582912 Apr 2 01:13 ibtmp1
- drwxr-x--- 2 mysql mysql 4096 Apr 2 01:12 mysql
- -rw-r----- 1 mysql mysql 177 Apr 2 01:12 mysql-bin.000001
- -rw-r----- 1 mysql mysql 3039401 Apr 2 01:12 mysql-bin.000002
- -rw-r----- 1 mysql mysql 154 Apr 2 01:12 mysql-bin.000003
- -rw-r----- 1 mysql mysql 57 Apr 2 01:12 mysql-bin.index
- drwxr-x--- 2 mysql mysql 4096 Apr 2 01:12 performance_schema
- -rw------- 1 mysql mysql 1675 Apr 2 01:12 private_key.pem
- -rw-r--r-- 1 mysql mysql 451 Apr 2 01:12 public_key.pem
- -rw-r--r-- 1 mysql mysql 1107 Apr 2 01:12 server-cert.pem
- -rw------- 1 mysql mysql 1675 Apr 2 01:12 server-key.pem
- drwxr-x--- 2 mysql mysql 12288 Apr 2 01:12 sys
- root@ae594a28192d:/var/lib/mysql#
设置同步时, 若 MASTER_LOG_FILE 有误会怎么样? 来试试:
1. 进入 MySQL 第一从库容器, 再进入 MySQL 命令行;
2. 执行 stop slave; 停止同步;
3. 执行以下 SQL 重新设置同步参数, 其中 MASTER_LOG_FILE 已被改成一个不存在的文件名 "mysql-bin.999999":
- CHANGE MASTER TO MASTER_HOST='masterhost', \
- MASTER_USER='rep', \
- MASTER_PASSWORD='888888', \
- MASTER_LOG_FILE='mysql-bin.999999', \
- MASTER_LOG_POS=154;
4. 执行 start slave; 开始同步;
5. 执行 show slave status\G 查看同步状态, 发现 "Last_IO_Error" 字段的值如下, 提示找不到 binlog 文件:
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
6. 此时在主库的 MySQL 命令行执行 SQL 新增一条记录: insert into test_table(name) values ('tom');;
7. 回到第一从库查看 test_table 表, 发现数据没有同步过来;
8. 去第二从库查看 test_table 表, 数据同步正常:
小结: MASTER_LOG_FILE 的值与主库同步的 binlog 名不一致会导致同步失败;
查看 binlog 文件
接下来看看 MASTER_LOG_POS 参数的作用, 我们把之前的容器全部清除再重新来验证:
1. 在 docker-compose.yml 文件所在目录下执行 docker-compose down, 将一主二从容器全部删除;
2. 在 docker-compose.yml 文件所在目录下执行 docker-compose up -d, 像Docker 下 MySQL 主从三部曲之一: 极速体验一样重新创建一主二从;
3. 进入第一从库, 在 MySQL 命令行执行 stop slave;, 将主从同步停止;
4. 在 MySQL 主库的命令行执行以下命令, 创建数据库, 表, 新增记录:
- create database test001;
- use test001;
- CREATE TABLE `test_table` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(100) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- insert into test_table(name) values ('jerry');
5. 执行 show master status;, 查出 binlog 文件名为 mysql-bin.000003;
6. 推出 MySQL 命令行, 执行 mysqlbinlog /var/lib/mysql/mysql-bin.000003> ~/mysql-bin.000003.txt 将 binlog 文件转成可读的文本文件;
7. 打开文件~/mysql-bin.000003.txt, 看到如下内容:
- SET @@session.collation_database=DEFAULT/*!*/;
- create database test001
- /*!*/;
- # at 322
- #180402 12:37:52 server id 1 end_log_pos 387 CRC32 0xa2118048 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no
- SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
- # at 387
- #180402 12:37:52 server id 1 end_log_pos 628 CRC32 0x4eb6b868 Query thread_id=4 exec_time=1 error_code=0
- use `test001`/*!*/;
- SET TIMESTAMP=1522672672/*!*/;
- CREATE TABLE `test_table` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(100) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8
- /*!*/;
- # at 628
- #180402 12:37:57 server id 1 end_log_pos 693 CRC32 0x37e9fbe9 Anonymous_GTID last_committed=2 sequence_number=3 rbr_only=ye
- s
- /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
- SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
- # at 693
- #180402 12:37:57 server id 1 end_log_pos 768 CRC32 0x0a4b387b Query thread_id=4 exec_time=0 error_code=0
- SET TIMESTAMP=1522672677/*!*/;
- BEGIN
- /*!*/;
- # at 768
- #180402 12:37:57 server id 1 end_log_pos 827 CRC32 0x45fec29f Table_map: `test001`.`test_table` mapped to number 108
- # at 827
- #180402 12:37:57 server id 1 end_log_pos 874 CRC32 0x620435ef Write_rows: table id 108 flags: STMT_END_F
- BINLOG '
- JSTCWhMBAAAAOwAAADsDAAAAAGwAAAAAAAEAB3Rlc3QwMDEACnRlc3RfdGFibGUAAgMPAiwBAp/C
- /kU=
- JSTCWh4BAAAALwAAAGoDAAAAAGwAAAAAAAEAAgAC//wBAAAABQBqZXJyee81BGI=
- '/*!*/;
- # at 874
- #180402 12:37:57 server id 1 end_log_pos 905 CRC32 0x6128e936 Xid = 29
- COMMIT/*!*/;
- SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog *//*!*/;
- DELIMITER ;
- # End of log file
从上述内容可以看到, 每次写入操作之后都会有个# at xxx 这样的标记, 这就是 MASTER_LOG_POS 对应的数字;
8. 将上面的几个关键点整理成下面的表格:
at 值 | at 前面的操作 |
---|---|
154 | 此位置之后会执行创建数据库的操作 |
322 | 创建数据库 |
628 | 创建表 |
874 | 向表中新增一条记录 |
修改 MASTER_LOG_POS
接下来我们修改 MASTER_LOG_POS 参数试试:
1. 进入第一从库容器的 MySQL 命令行;
2. 执行下面的 SQL, 令 MASTER_LOG_POS 等于 628, 也就是不包含创建数据库和创建表的 binlog 内容:
- CHANGE MASTER TO MASTER_HOST='masterhost', \
- MASTER_USER='rep', \
- MASTER_PASSWORD='888888', \
- MASTER_LOG_FILE='mysql-bin.000003', \
- MASTER_LOG_POS=628;
3. 进入第一从库, 在 MySQL 命令行执行 start slave;, 将主从同步启动;
4. 执行 show slave status\G 查看同步状态, 看到 Last_SQL_Error 字段的内容如下:
Last_SQL_Error: Error executing row event: 'Table'test001.test_table'doesn't exist'
如上所示, MASTER_LOG_POS 参数指定的 AT 数字之后的 binlog 才会被执行, 之前的是不执行的;
5. MySQL 命令行执行 stop slave;, 将主从同步停止;
6. 执行下面的 SQL, 令 MASTER_LOG_POS 等于 154, 也就是创建数据库之前的位置:
- CHANGE MASTER TO MASTER_HOST='masterhost', \
- MASTER_USER='rep', \
- MASTER_PASSWORD='888888', \
- MASTER_LOG_FILE='mysql-bin.000003', \
- MASTER_LOG_POS=154;
7. MySQL 命令行执行 start slave;, 将主从同步启动;
8. 查看同步状态, 已经正常, 再去查数据库数据, 也已经同步过来了:
- mysql> show databases;
- +--------------------+
- | Database |
- +--------------------+
- | information_schema |
- | mysql |
- | performance_schema |
- | sys |
- | test001 |
- +--------------------+
- 5 rows in set (0.00 sec)
- mysql> use test001;
- 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 test_table;
- +----+-------+
- | id | name |
- +----+-------+
- | 1 | jerry |
- +----+-------+
- 1 row in set (0.00 sec)
到这里, 对 MASTER_LOG_POS 参数的实战就结束了, 该参数与 binlog 中的 "at" 标记对应, 如果设置不当, 会导致前面的 SQL 操作丢失, 在遇到有依赖的同步操作时就会有问题;
至此, Docker 下 MySQL 主从三部曲就全部结束了, 希望能够给您的 Docker 实战带来一些参考, 助您做出更实用的镜像;
来源: https://blog.csdn.net/boling_cavalry/article/details/79782008