1. 程式人生 > >Docker下MySQL主從三部曲之三:binlog日誌引數實戰

Docker下MySQL主從三部曲之三:binlog日誌引數實戰

本章是《Docker下MySQL主從三部曲》的終篇,前面的章節我們能夠製作映象來搭建主從同步環境,本章我們來觀察binlog引數MASTER_LOG_POS

關於從庫同步的設定

在設定從庫同步的時候一般會使用以下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;
  • 1
  • 2
  • 3
  • 4
  • 5

今天我們的實戰和上面的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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如上所示,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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

根據以上配置資訊,我們在/var/lib/mysql目錄下找到了bin log檔案mysql-bin.000003,如下:

[email protected]:/var/lib/mysql# pwd
/var/lib/mysql
[email protected]:/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
[email protected]:/var/lib/mysql# 
  • 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

設定同步時,若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;
  • 1
  • 2
  • 3
  • 4
  • 5


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'
  • 1


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');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11


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
  • 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

從上述內容可以看到,每次寫入操作之後都會有個# 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;
  • 1
  • 2
  • 3
  • 4
  • 5


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'
  • 1

如上所示,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;
  • 1
  • 2
  • 3
  • 4
  • 5


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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

到這裡,對MASTER_LOG_POS引數的實戰就結束了,該引數與binlog中的“at”標記對應,如果設定不當,會導致前面的SQL操作丟失,在遇到有依賴的同步操作時就會有問題;

至此,Docker下MySQL主從三部曲就全部結束了,希望能夠給您的Docker實戰帶來一些參考,助您做出更實用的映象;