【20180608】MySQL5.7新增表mysql.gtid_executed

MySQL5.7新增表mysql.gtid_executed

MySQL5.6主從,從庫獲取gtid_executed

在MySQL5.6的時候,主從複製開啓了GTID,在slave執行show slave status \G的時候可以獲取得到當前執行的GTID的集合信息。在MySQL5.6的時候這個值並不是持久化到文件或者數據庫表中的,而是每次在slave重啓的時候從最後一個binlog文件的末尾讀取寫入內存中去的。那麼這個樣子就會造成一個問題,在從庫沒有開啓log_slave_updates這個參數的時候或者說維護人員不小心將binlog文件給刪除了之後,那麼slave重啓之後就會獲取不到gtid_executed的值,那麼主從環境就會掛掉。

並且還需要注意的一點就是,就算我們開啓了log_slave_updates這個參數,將所有來自於master的事務在本地回放的時候寫入slave本地的binlog中去的話,那麼不可避免會造成磁盤IO和磁盤空間資源的浪費。

MySQL5.7新增的mysql.gtid_executed

在MySQL5.7的時候則將gtid_executed的信息持久化到了表中,這個表就是mysql.gtid_executed表:

root@mysqldb 11:03:  [(none)]> show create table mysql.gtid_executed \G
*************************** 1. row ***************************
       Table: gtid_executed
Create Table: CREATE TABLE `gtid_executed` (
  `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.',
  `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.',
  `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.',
  PRIMARY KEY (`source_uuid`,`interval_start`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 STATS_PERSISTENT=0

執行SQL可以看到這個表的一些具體信息:

root@mysqldb 11:04:  [(none)]> select * from mysql.gtid_executed ;
+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 4725234c-1acc-11e8-9ff9-000c29a80f41 |              1 |          781 |
| 4725234c-1acc-11e8-9ff9-000c29a80f41 |            989 |         1011 |
| 4cf4a087-1ba3-11e8-92f6-000c2920ceb4 |              1 |         2239 |
+--------------------------------------+----------------+--------------+
3 rows in set (0.00 sec)

新增mysql.gtid_executed表之後,slave重啓之後可以直接從這個表中獲取信息。需要注意的是mysql.gtid_executed是在主從服務器上面都會進行更新的,而表slave_relay_log_info僅僅只是在從服務器進行更新的。

可以看到上述的表mysql.gtid_executed並沒有記錄每個事務的GTID的值,而是記錄了GTID的起始值和末尾值,這個是因爲爲了避免這個表的記錄瘋狂的增長,所以MySQL5.7引入了一個新的進程進行專門的壓縮,並且有專門的參數來設置這個壓縮比。

root@mysqldb 11:58:  [(none)]> select thread_id,thread_os_id,name,processlist_command,processlist_state from performance_schema.threads where name like '%compress%';
+-----------+--------------+--------------------------------+---------------------+-------------------+
| thread_id | thread_os_id | name                           | processlist_command | processlist_state |
+-----------+--------------+--------------------------------+---------------------+-------------------+
|        27 |        23839 | thread/sql/compress_gtid_table | Daemon              | Suspending        |
+-----------+--------------+--------------------------------+---------------------+-------------------+
1 row in set (0.00 sec)

root@mysqldb 11:59:  [(none)]> show global variables like 'gtid_executed_compression_period';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| gtid_executed_compression_period | 1000  |
+----------------------------------+-------+
1 row in set (0.01 sec)

root@mysqldb 11:59:  [(none)]>

還有一點需要我們注意的:mysql.gtid_executed的記錄方式是和從庫是否開啓記錄二進制日誌是有很大的關係的。若是slave開啓了二進制日誌,則該表只會在二進制日誌切割的時候或者MySQL正常關閉進行更新,否則的話就會進行實時的更新。還有需要注意的一點就是,在MySQL異常關閉的時候GTID的信息是不會記錄到這個表中的,在MySQL恢復的時候會從binlog中記錄寫入這個表中的。

當binlog開啓的時候,並且exectued_gtids_compression_period值未使用的時候,MySQL的binlog輪換也會引起mysql.gtid_executed表的自動壓縮。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章