天天看點

MySQL中GTID和自增列的資料測試(r12筆記第38天)

  昨天的一篇文章,今天有不少網友向我确認一些細節,我想最近正好在看GTID的東西,可以揉在一起來說說。

   GTID這個概念看似簡單,實際上還是有不少的門道。

我們來從架構的設計角度來看看存在哪些場景需要考慮GTID的變化。  

一主兩從的架構模式下GTID的變化

  我們就以一主兩從的架構為基準進行闡述。在這個架構模式下我們會用到MHA的方案。

MySQL中GTID和自增列的資料測試(r12筆記第38天)

如果這個時候Master節點當機了,MHA就會開啟檢查機制。

MySQL中GTID和自增列的資料測試(r12筆記第38天)

這個時候Slave 1節點就會變為新的Master,Slave 2會從Slave 1上重新應用資料變更,這個時候GTID是怎麼變化的,從庫的Executed GTID Set到底是一個還是兩個。

MySQL中GTID和自增列的資料測試(r12筆記第38天)

這個場景繼續往下延伸。如果當機的主庫啟動之後,假設是硬體問題,比如電源故障燈原因,Master節點啟動了,那麼Master節點的重新加入主從環境中GTID是如何變化的。這樣就是下面的架構圖了。

MySQL中GTID和自增列的資料測試(r12筆記第38天)

而我們把這個問題繼續細化,那就是和自增列值的問題結合起來。看看在這種場景下,MySQL的實作方式是否會出現資料不一緻,無法複制的情況。兩者結合起來算是一個相對完整的測試場景了。當然我要标記為第一篇,因為還會有第二篇出來。

 我們看看如何操作。

一主兩從的架構模式下GTID的實踐

一主兩從我們辨別為主(Master節點),從庫1(Slave 1),從庫2 (Slave 2),大體的測試步驟如下:

初始化一主兩從

Master節點初始化資料,測試自增列值

配置MHA,Master節點當機

MHA切換,Slave 1節點升為主庫,Slave 2節點為從庫

Master節點啟動

Master節點加入主從複制環境

步驟1:初始化,得到一主兩從的GTID情況

步驟1相對簡單,可以使用sandbox或者是快速腳本的方式搭建。

搭建完成後,先來看看Gtid的情況。

mysql> show master status\G

*************************** 1. row ***************************

             File: binlog.000001

         Position: 1475

     Binlog_Do_DB:

 Binlog_Ignore_DB:

Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-7

檢視server_uuid的情況如下:

mysql> show global variables like 'server_uuid%';

+----------------+--------------------------------------+

| Variable_name  | Value                                |

| server_uuid    | 4f7b0b93-2400-11e7-99cb-782bcb377193

3 rows in set (0.01 sec)我們後續的測試都會參考這個值。

Slave 1節點的情況如下,和Master節點的server_uuid明顯不同。這個資訊可以在初始化的目錄auto.cnf可以得到。

mysql> show global variables like 'server%';

| server_id      | 24802                                |

| server_id_bits | 32                                   |

| server_uuid    | 5433468e-2400-11e7-a834-782bcb377193

+----------------+--------------------------------------+檢視master status的資訊如下,這一點可以看出是和Master節點的Gtid Set值相同,證明這個Gtid的值是一個唯一性辨別,當然從GTID的全稱就是全局事務辨別。

         Position: 438

1 row in set (0.00 sec)我們來看看show slave status的結果。

mysql> show slave status\G

               Slave_IO_State: Waiting for master to send event

                  Master_Host: 10.127.128.78

                  Master_User: rpl_user

。。。           

           Retrieved_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:6-7

            Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-7

。。。

1 row in set (0.00 sec)

步驟2:初始化Master節點,測試自增列問題

步驟2我們來初始化一下Master節點。就建立一個資料庫test

create database test;Slave 1節點的情況如下,可以看到末尾的事務ID序号開始增加。

         Position: 589

Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-8下面的初始化就是關鍵了,我們會測試自增列的情況,來複現一個經典問題。建立一個表t1,然後插入3條記錄。

mysql>  drop table if exists t1;

mysql> create table t1(id int auto_increment, a int, primary key (id)) engine=innodb;

mysql> insert into t1 values (1,2);

mysql> insert into t1 values (null,2);

mysql> select *from t1;

+----+------+

| id | a    |

|  1 |    2 |

|  2 |    2 |

|  3 |    2 |

+----+------+毫無疑問,這個時候自增列的值是4.

mysql> show create table t1\G

       Table: t1

Create Table: CREATE TABLE `t1` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `a` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1在Slave 1節點和Slave 2節點得到的資料情況是一緻的,都是4

然後我們做下面的變更,删除表中id=3的值。這個情況也很容易了解,那就是自增列不會變化。

mysql> delete from t1 where id=3;

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

Slave 1節點和Slave 2節點也是如此,自增列值都是4

步驟3:配置MHA,Master節點當機

這個步驟可以參考 sandbox和MHA快速測試(r12筆記第32天),對MHA的配置有一個基本的介紹,可以使用如下的兩個腳本來做基本的檢驗,app1.cnf就是基礎的配置檔案。内容大體如下:

[server default]

manager_workdir=/home/mha/manager

manager_log=/home/mha/manager/app1/manager.log

port=24801   -指定的端口

user=mha_test

password=mha_test  --需要提前建立

repl_user=rpl_user

repl_password=rpl_pass

master_ip_failover_script= /home/mha/conf/master_ip_failover2

# shutdown_script= /script/masterha/power_manager

# report_script= /script/masterha/send_report

# master_ip_online_change_script= /script/masterha/master_ip_online_change

[server1]

hostname=10.127.128.78

port=24801

candidate_master=1

[server2]

port=24802

[server3]

port=24803ssh的互信檢查。

# masterha_check_ssh  --conf=app1.cnf主從複制的檢查。

# masterha_check_repl  --conf=app1.cnf  

檢查無誤後,我們啟動MHA manager服務。

nohup masterha_manager --conf=/home/mha/conf/app1.cnf  > /tmp/mha_manager.log 2>&1 &

然後我們查到對應的程序号,直接Kill即可。

[root@grtest app1]# ps -ef|grep 24801

mysql     2168  1918  0 14:29

pts/7    00:00:00 /usr/local/mysql/bin/mysqld

--defaults-file=/home/data/s1/s1.cnf --basedir=/usr/local/mysql_5.7.17

--datadir=/home/data/s1 --plugin-dir=/usr/local/mysql_5.7.17/lib/plugin

--user=mysql --log-error=/home/data/s1/grtest.err

--pid-file=/home/data/s1/grtest.pid --socket=/home/data/s1/s1.sock

--port=24801

root      3623 12108  0 14:40 pts/7    00:00:00 grep 24801

[root@grtest app1]# kill -9 1918 2168我們簡單描述一下,Master節點殺掉後,主庫的表t1的自增列值如果啟動之後就會是3,即上一次的max(id)+1開始計算。而從庫的自增列值為4,這個該怎麼平衡呢?

步驟4:MHA切換,Slave1節點為主庫

整個切換的過程是自動完成的,MHA會檢測心跳,然後自動開始切換主從複制關系。整個過程GTID就是一個需要注意的地方。

Started automated(non-interactive) failover.

Invalidated master IP address on 10.127.128.78(10.127.128.78:24801)

Selected 10.127.128.78(10.127.128.78:24802) as a new master.

10.127.128.78(10.127.128.78:24802): OK: Applying all logs succeeded.

10.127.128.78(10.127.128.78:24802): OK: Activated master IP address.

10.127.128.78(10.127.128.78:24803): OK: Slave started, replicating from 10.127.128.78(10.127.128.78:24802)

10.127.128.78(10.127.128.78:24802): Resetting slave info succeeded.

Master failover to 10.127.128.78(10.127.128.78:24802) completed successfully.于是Slave 1節點就正式接管環境。

檢視新主庫Slave 1節點的資訊如下,這個GTID還是原來Master節點的。

         Position: 1895

Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-14server_uuid的部分還是原來的設定。

| server_uuid    | 5433468e-2400-11e7-a834-782bcb377193 |

+----------------+--------------------------------------+這個地方需要關注,那就是檢視自增列的情況,因為原來是從庫,是以得到的最新值為4.

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1在這種情況下Slave 2節點就會重新調整複制關系,

                  Master_Port: 24802

           Retrieved_Gtid_Set:

            Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-14

                Auto_Position: 1

檢視自增列的情況如下:

這裡可能會有些疑惑,而且對于GTID的了解會有一些誤差,我們在Slave 1節點上插入一行資料。

mysql> insert into t1 values(null,2);這個時候檢視自增列的情況如下,會逐漸遞增。

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1這個時候就需要重新檢視下Gtid的情況了。可以看到這裡有原來Master節點的server_uuid,也有目前新主庫的server_uuid值。

         Position: 2133

Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-14,

5433468e-2400-11e7-a834-782bcb377193:1   

新的從庫Slave 2節點的資訊如下:

節點3:

mysql>

      。。。

           Retrieved_Gtid_Set: 5433468e-2400-11e7-a834-782bcb377193:1

            Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-14,

是以可以發現failover以後的自增列值不會受到影響,而且GTID set會包含目前主庫和原來的主庫資訊。

步驟5:Master節點啟動

啟動Master節點步驟相對簡單。

#  /usr/local/mysql_5.7.17/bin/mysqld_safe --defaults-file=/home/data/s1/s1.cnf &啟動之後有很多細節需要确認,一個是關于master status的資訊。

Empty set (0.00 sec)

             File: binlog.000002

         Position: 190

Executed_Gtid_Set: 4f7b0b93-2400-11e7-99cb-782bcb377193:1-14這個地方明顯不對,那是因為主從複制關系還沒有調整。

我們看看這個時候的自增列值情況。糾結的問題就是自增列之為3,而Slave 1節點和Slave 2節點的自增列值為5.

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1

步驟:6:Master節點加入主從複制環境

重新配置主從複制關系:

CHANGE MASTER TO MASTER_HOST='10.127.128.78', MASTER_PORT=24802,

MASTER_AUTO_POSITION=1, MASTER_USER='rpl_user',

MASTER_PASSWORD='rpl_pass';啟動新的從庫,啟動後會發現GTID會是兩個。

mysql> start slave;

   。。。

5433468e-2400-11e7-a834-782bcb377193:1

。。。這個時候再次檢視自增列的情況。這個步驟看起來複雜一些,其實就是新的從庫會去接收應用在Slave 1節點上的資料變化,相當于在Master節點插入了一條記錄,導緻這個自增列之繼續增加。

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1  --id值 恢複了

1 row in set (0.00 sec)我們可以檢視binlog的資訊來進行基本的驗證。

[root@grtest app1]# /usr/local/mysql_5.7.17/bin/mysqlbinlog -vv /home/data/s1/binlog.000002

...

BEGIN

/*!*/;

# at 310

#170418 14:44:01 server id 24802  end_log_pos 352       Table_map: `test`.`t1` mapped to number 219

# at 352

#170418 14:44:01 server id 24802  end_log_pos 392       Write_rows: table id 219 flags: STMT_END_F

BINLOG '

sbX1WBPiYAAAKgAAAGABAAAAANsAAAAAAAEABHRlc3QAAnQxAAIDAwAC

sbX1WB7iYAAAKAAAAIgBAAAAANsAAAAAAAEAAgAC//wEAAAAAgAAAA==

'/*!*/;

### INSERT INTO `test`.`t1`

### SET

###   @1=4 /* INT meta=0 nullable=0 is_null=0 */

###   @2=2 /* INT meta=0 nullable=1 is_null=0 */

# at 392

#170418 14:44:01 server id 24802  end_log_pos 419       Xid = 19

COMMIT/*!*/;

SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;

DELIMITER ;

# End of log file

/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;

/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;這樣一來對于GTID的了解就會更加清晰一些。對于自增列的問題也會更加明确,确确實實目前能夠解決資料不一緻的情況。

繼續閱讀