[數據庫] 淺談mysql的serverId/serverUuid

0 序

  • 版本

本文圍繞 mysql 5.7.38 版本開展討論

  • 情景1:
  • MYSQL數據庫的主從複製架構:1主1從
  • MYSQL數據庫的binlog應用情況:存在多個基於binlog同步機制的FlinkCdcJob,從MYSQL中增量同步數據
  • 某一天,FlinkCdcJob報如下錯誤:
ConnectException: A slave with the same server_uuid/server_id as this slave has connected to the master; the first event '' at 4, the last event read from './mysql-bin.152542' at 1380734, the last byte read from './mysql-bin.152542' at 1380734. Error code: 1236; SQLSTATE: HY000.

【翻譯】ConnectException:與該從服務器具有相同server_uuid/server_id的從服務器已連接到主服務器;第一個事件在第 4 行,最後一個事件從'./mysql-bin '讀取。152542' at 1380734,從'./mysql-bin '讀取的最後一個字節。152542' at 1380734。錯誤碼:1236;SQLSTATE: HY000。

【特別說明】基於binlog同步機制的FlinkCdcJob應用程序,本質上也是1個MySQL Slave

  • 情景2:
  • 當我們搭建MySQL集羣時,自然需要完成數據庫的主從同步來保證數據一致性
  • 主從同步的實現方式也分很多種:一主一從一主多從鏈式主從多主多從。可根據你的需要來進行設置。
  • 但只要你需要主從同步,就一定要注意server-id的配置,否則會出現主從複製異常
  • 在控制數據庫數據複製日誌管理中,有2個重要的配置:server-idserver-uuid

它們會影響二進制日誌文件記錄全局事務標識

1 server-id 概述

server-id的查看與配置

  • 當你使用主從拓撲時,一定要對所有MySQL實例都分別指定一個獨特的互不相同的server-id

  • 默認值爲0,當server-id=0時,對於主機來說依然會記錄二進制日誌,但會拒絕所有的從機連接;對於從機來說則會拒絕連接其它實例

  • MySQL實例的server-id是一個全局變量,可以直接查看:

mysql> show variables like '%server_id%';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| server_id     | 171562767 |
+---------------+-----------+
1 row in set (0.00 sec)

mysql> show variables like '%server%id%';
server_id	    4198984507
server_id_bits	32
server_uuid	    c5df5b9e-3d7d-11ed-accf-fa163e42a616
  • server-id的配置/修改。

我們可以在線直接修改全局變量server-id,但不會立即生效,所以修改後記得重啓服務。
而重啓後又會重新讀取系統配置文件配置,導致剛纔的修改失效,因此建議修改配置文件後重啓服務而不是在線修改。

# my.cnf
[mysqld]
#replication
log-bin=mysql-bin
server-id=171562767
sync_binlog=1
binlog-ignore-db=mysql
binlog-ignore-db=information_schema

server-id的用途與影響分析

  • server-id用於標識數據庫實例,防止在鏈式主從多主多從拓撲中導致SQL語句的無限循環
  1. 標記binlog event的源實例
  2. 過濾主庫binlog,當發現server-id相同時,跳過該event執行,避免無限循環執行
  3. 如果設置了replicate-same-server-id=1,則:執行所有event,但有可能導致無限循環執行SQL語句

我們用兩個例子來說明server-id爲什麼不要重複

  • 主庫備庫server-id重複時:

由於默認情況replicate-same-server-id=0,因此備庫會跳過所有主庫同步的數據,導致主從數據的不一致。

  • 當兩個備庫server-id重複時:

會導致從庫主庫的連接時斷時連,產生大量異常。
根據MySQL的設計,主庫從庫通過事件機制進行連接和同步,當新的連接到來時,如果發現server-id相同,主庫會斷開之前的連接並重新註冊新連接。
當A庫連接上主庫時,此時B庫連接到來,會斷開A庫連接,A庫再進行重連,週而復始導致大量異常信息。

生成server-id的規則

既然server-id不能相同,而當我們有10個實例時,怎麼保證每個都不同呢?有幾種常用的方法:

  1. 隨機數
  2. 時間戳
  3. IP地址+端口
  4. 在管理中心集中分配,生成自增ID

上面的這些方法都可以,但是注意不要超過了最大值2^32-1,同時值最好>2

推薦採用的方法是:IP地址後兩位+本機MySQL實例序號

但如果是通過docker來進行管理多實例時,這個怎麼生成大家可以想下有沒有什麼優美的解決方案。

2 server-uuid概述

  • MySQL服務會自動創建並生成server-uuid配置:
  1. 讀取${data_dir}/auto.cnf文件中的UUID
  2. 如果不存在,自動創建文件和生成新的UUID並讀取
shell> cat ~/mysql/data/auto.cnf
[auto]
server-uuid=fd5d03bc-cfde-11e9-ae59-48d539355108
  • 查驗方式
mysql> show variables like '%server%id%';
server_id	    4198984507
server_id_bits	32
server_uuid	    c5df5b9e-3d7d-11ed-accf-fa163e42a616
  • 這個auto.cnf配置風格類似於my.cnf,但這個文件只包含一個auto配置塊和一行server-uuid配置。它是自動創建的,因此不要修改它的內容。
  • 在主從拓撲中,主從可以知道互相的UUID,在主機上使用show slave hosts,在從機上使用show slave status查看Master_UUID字段。
  • server-uuid參數並不能取代server-id,他們有不同的作用。當主從同步時,如果主從實例的server-uuid相同會報錯退出,不過我們可以通過設置replicate-same-server-id=1來避免報錯(但不推薦)。

3 補充:MYSQL主從複製場景

show variables like '%server%id%' | 在主庫、從庫中查看

  • 查詢樣例:
server_id	    4198984507
server_id_bits	32
server_uuid	    c5df5b9e-3d7d-11ed-accf-fa163e42a616

show slave hosts | 在主庫查看

  • show slave hosts
  • 顯示當前配置爲複製從服務器(slave)的主機信息(包含了所有配置爲複製從服務器的主機信息)
  • 通常用於快速檢查和驗證哪些服務器被配置爲複製數據,以及它們的網絡連接狀態
  • 在MySQL 5.7及更高版本中使用的,而在更早的版本中,可能需要使用SHOW SLAVE STATUS;命令來獲取類似的信息
  • 查詢樣例:
mysql> show slave hosts
Server_id Host Port Master_id ------------------------------------
166523813 3306 1306176980 a8bdde3e-8008-11ed-83c4-fa163e5eb848

沒有主從複製架構的MYSQL實例,查詢結果爲空

show slave status | 在主庫查看

  • 查詢樣例:

X 參考文獻

MySQL 5.6 用 128 位的 server_uuid 代替了原本的 32 位 server_id 的大部分功能。
原因很簡單,server_id 依賴於 my.cnf 的手工配置,有可能產生衝突 —— 而自動產生 128 位 uuid 的算法可以保證所有的 MySQL uuid 都不會衝突。

在首次啓動時 MySQL 會調用 generate_server_uuid() 自動生成一個 server_uuid,並且保存到 auto.cnf 文件 —— 這個文件目前存在的唯一目的就是保存 server_uuid。

在 MySQL 再次啓動時會讀取 auto.cnf 文件,繼續使用上次生成的 server_uuid。

使用 SHOW 命令可以查看 MySQL 實例當前使用的 server_uuid​:SHOW GLOBAL VARIABLES LIKE 'server_uuid';
它是一個 MySQL 5.6 global variables

全局唯一的 server_uuid 的一個好處是:
可以解決由 server_id 配置衝突帶來的 MySQL 主備複製的異常終止

在 MySQL 5.6,Slave 向 Master 申請 binlog 時,會首先發送自己的 server_uuid,Master 用 Slave 發送的 server_uuid 代替 server_id (MySQL 5.6 之前的方式)作爲 kill_zombie_dump_threads 的參數,終止衝突或者僵死的 BINLOG_DUMP 線程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章