搞懂MySQL GTID原理


從MySQL 5.6.5 開始新增了一種基於 GTID 的復制方式。通過 GTID 保證了每個在主庫上提交的事務在集群中有一個唯一的ID。這種方式強化了數據庫的主備一致性,故障恢復以及容錯能力。

GTID (Global Transaction ID)是全局事務ID,當在主庫上提交事務或者被從庫應用時,可以定位和追蹤每一個事務,對DBA來說意義就很大了,我們可以適當的解放出來,不用手工去可以找偏移量的值了,而是通過CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION=1的即可方便的搭建從庫,在故障修復中也可以采用MASTER_AUTO_POSITION=‘X’的方式。

可能大多數人第一次聽到GTID的時候會感覺有些突兀,但是從架構設計的角度,GTID是一種很好的分布式ID實踐方式,通常來說,分布式ID有兩個基本要求:

1)全局唯一性

2)趨勢遞增

這個ID因為是全局唯一,所以在分布式環境中很容易識別,因為趨勢遞增,所以ID是具有相應的趨勢規律,在必要的時候方便進行順序提取,行業內適用較多的是基於Twitter的ID生成算法snowflake,所以換一個角度來理解GTID,其實是一種優雅的分布式設計。

1。如何開啟GTID

如何開啟GTID呢,我們先來說下基礎的內容,然后逐步深入,通常來說,需要在my.cnf中配置如下的幾個參數:

①log-bin=mysql-bin

②binlog_format=row

③log_slave_updates=1

④gtid_mode=ON

⑤enforce_gtid_consistency=ON

其中參數log_slave_updates在5.7中不是強制選項,其中最重要的原因在於5.7在mysql庫下引入了新的表gtid_executed。

在開始介紹GTID之前,我們換一種思路,通常我們都會說一種技術和特性能干什么,我們了解一個事物的時候更需要知道邊界,那么GTID有什么限制呢,這些限制有什么解決方案呢,我們來看一下。

2。 GTID的限制和解決方案

如果說GTID在5.6試水,在5.7已經發展完善,但是還是有一些場景是受限的。比如下面的兩個。

一個是create table xxx as select 的模式;另外一個是臨時表相關的,我們就來簡單說說這兩個場景。

1)create 語句限制和解法

create table xxx as select的語句,其實會被拆分為兩部分,create語句和insert語句,但是如果想一次搞定,MySQL會拋出如下的錯誤。

mysql> create table test_new as select *from test;

ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.

這種語句其實目標明確,復制表結構,復制數據,insert的部分好解決,難點就在於create table的部分,如果一個表的列有100個,那么拼出這么一個語句來就是一個工程了。

除了規規矩矩的拼出建表語句之外,還有一個方法是MySQL特有的用法 like。

create table xxx as select 的方式可以拆分成兩部分,如下。

create table xxxx like data_mgr;

insert into xxxx select *from data_mgr;

2)臨時表的限制和建議

使用GTID復制模式時,不支持create temporary table 和 drop temporary table。但是在autocommit=1的情況下可以創建臨時表,Master端創建臨時表不產生GTID信息,所以不會同步到slave,但是在刪除臨時表的時候會產生GTID會導致,主從中斷.

3。 從三個視角看待GTID

前面聊了不少GTID的內容,我們來看看GTID的一個體系內容,如下是我梳理的一個GTID的概覽信息,分別從變量視圖,表和文件視圖,操作視圖來看待GTID.

搞懂MySQL GTID原理

 

我們分別從每個視圖來簡單說下:

1)變量視圖

我們來用下面的表格來闡述下常見的這幾個變量

搞懂MySQL GTID原理

 

2)表和文件視圖

先來說下文件層面的關聯,根據MySQL的復制原理,MySQL Server在寫binlog的時候,會先寫一個特殊的Binlog Event,類型為GTID_Event,指定下一個事務的GTID,然后再寫事務的Binlog,主從同步時GTID_Event和事務的Binlog都會傳遞到從庫,在從庫應用Relay Log,從庫在執行的時候也是用同樣的GTID寫binlog.

然后說一下表mysql.gtid_executed,在5.6版本中必須要設置log_slave_updates,因為當slave重啟后,無法得知當前slave已經運行到的GTID位置,因為變量gtid_executed是一個內存值,而這個問題在5.7中通過表mysql.gtid_executed把這個值持久化來得以解決,也就意味着log_slave_updates是一個可選項。

此外,引入該解決方案之后又帶來了新的問題,那就是在gtid_executed里面的數據會越來越多,如何精簡管理呢,MySQL引入了一個新的線程和參數來進行管理。

線程為:thread/sql/compress_gtid_table,可以查詢performance_schema.threads來查看。

參數為 gtid_executed_compression_period ,主要用於控制每執行多少個事務,對表gtid_executed進行壓縮,默認值為:1000 。

3)操作視圖

對於操作,我們列舉了較為簡單常規的操作方式,為了避免歧義,我對一些命令做了取舍。

這些主要是在搭建主從復制關系時所用,基本都是一次開啟,長期生效的方式。

如果是修復主從復制中的異常,如果是在確認錯誤可以跳過的情況下,可以使用如下的方式:

l stop slave;

l set gtid_next='xxxxxxx:N'; --指定下一個事務執行的版本,即想要跳過的GTID

l begin;

l commit; --注入一個空事物

l set gtid_next='AUTOMATIC' --自動的尋找GTID事務。

l start slave; --開始同步


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM