1. 程式人生 > 其它 >Mysql雙主架構及其異常

Mysql雙主架構及其異常

2022-05-18T10:54:29.211484+08:00 124482968 [ERROR] Slave SQL for channel '': Worker 1 failed executing transaction '284aaa9b-ac5d-11ea-8559-005056814878:1025875055' at master log mysql-bin.001266, end_log_pos 254572627; Column 10 of table 'bi.zmmr0051' cannot be converted from type 'varchar(210(bytes))' to type 'varchar(300(bytes) utf8)', Error_code: 1677

  

1.mysql架構為mysql雙主,master-1和master-2分別寫入不同的表

2.mysql雙主配置檔案

[mysqld]
#***********base***************
basedir=/usr/local/mysql
datadir=/flex/mysql/data/mysql3306/var
socket=/flex/mysql/data/mysql3306/tmp/mysql.sock
port=3306
server-id=141  //master-1和master-2的server-id應不一樣
skip-name-resolve
skip-slave-start
lower_case_table_names
=1 transaction-isolation=READ-COMMITTED default-time_zone = '+8:00' log_timestamps=SYSTEM ##**********connection************ max_connections=500 max_connect_errors=100000 max_user_connections=300 ####********binlog & relaylog******** log-error=/flex/mysql/data/mysql3306/log/mysql.err log_bin=/flex/mysql/data/mysql3306/
var/mysql-bin binlog_cache_size=128k binlog_stmt_cache_size=128k max_binlog_cache_size=4G max_binlog_stmt_cache_size=4G binlog_format=row expire_logs_days=7 max_binlog_size=500M sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION relay_log_recovery=ON gtid-mode=on enforce-gtid-consistency=on slow_query_log=1 slow_query_log_file=/flex/mysql/data/mysql3306/var/slow.log long_query_time=2 log_queries_not_using_indexes=ON log-bin-trust-function-creators=1 ###*******character set************** character_set_server=utf8 ###*******ignore&&define repl database******** #replicate-do-db=bi replicate-ignore-db=mysql replicate-ignore-db=information_schema replicate-ignore-db=performance_schema ##*************** buffer & timeout *************** innodb_buffer_pool_size=8G # ##*************** muti thread slave *************** slave_parallel_type =LOGICAL_CLOCK slave_parallel_workers=4 master_info_repository=TABLE relay_log_info_repository=TABLE slave_preserve_commit_order =1 ##*************** group commit *************** binlog_group_commit_sync_delay =1 binlog_group_commit_sync_no_delay_count =1000 sync_binlog=1 innodb_flush_log_at_trx_commit=2 # ##*********** innodb *************** innodb_undo_directory =/flex/mysql/data/mysql3306/var/undo innodb_undo_log_truncate=on innodb_max_undo_log_size=1024M innodb_undo_tablespaces=3 autocommit=1 default_storage_engine =InnoDB default_tmp_storage_engine =InnoDB internal_tmp_disk_storage_engine =InnoDB ###***********slave****************************** log-slave-updates=1 //該值決定從庫的relaylog是否同時計入binlog,為1是計入,為0是不記錄,預設為0,如果從庫作為其他資料庫的主庫應當開啟,此引數和-log_bin結合使用,雙主架構需設為1 log-bin-trust-function-creators=1 # [mysql] socket=/flex/mysql/data/mysql3306/tmp/mysql.sock

3.異常現象

開發通過navicate修改某張表的欄位屬性,由varchar(4) -->varchar(8)

導致異常:看字面意思就是對端節點無法執行type轉化,但是實際上對端資料庫修改成功

解決:

經過了種種方法解決,均為成功,無奈和開發溝通,整庫重建主主架構,才解決

2022-05-18T10:54:29.211484+08:00 124482968 [ERROR] Slave SQL for channel '': 
Worker 1 failed executing transaction '284aaa9b-ac5d-11ea-8559-005056814878:1025875055'
at master log mysql-bin.001266, end_log_pos 254572627; Column 10 of table 'bi.zmmr0051'
cannot be converted from type 'varchar(210(bytes))' to type 'varchar(300(bytes) utf8)', Error_code: 1677

4.GTID

此問題引發了我對GTID的又一輪理解,包括一些錯誤理解

mysql主主架構的同步原理:

1).Master-1 所有資料庫變更寫進 Binary Log, master-1庫執行緒 Binlog Dump 把 Binary Log 內容傳送到master-2庫 上(master-2庫被動接受資料,不是主動去獲取)。
2).master-2 Io 執行緒讀取 Master-1上 Binary Log 日誌資訊,把接受到的 Binary Log 日誌寫到本地中繼日誌 Relay Log
3).Slave Sql 執行緒讀取 Ralay Log 日誌內容寫入本地資料庫例項,並寫入本地的binlog
4).binglog採用gtid具有全域性唯一性,所以master-1不會二次執行

5.GTID的原理:

5.1 GTID 的概述:
1、全域性事物標識:global transaction identifieds。

2、GTID 事物是全域性唯一性的,且一個事務對應一個 GTID。

3、一個 GTID 在一個伺服器上只執行一次,避免重複執行導致資料混亂或者主從不一致。

4、GTID 用來代替classic的複製方法,不在使用 binlog+pos 開啟複製。而是使用 master_auto_postion=1 的方式自動匹配 GTID 斷點進行復制。

5、MySQL-5.6.5 開始支援的,MySQL-5.6.10 後開始完善。

6、在傳統的 slave 端,binlog 是不用開啟的,但是在 GTID 中,slave 端的 binlog 是必須開啟的,目的是記錄執行過的 GTID(強制);但是從 5.7.5 版本開始無需在 GTID 模式下啟用引數 log_slave_updates

 5.2 GTID 的組成部分:

GTID = source_id:transaction_id

source_id 正常即是 server_uuid,在第一次啟動時生成(函式 generate_server_uuid),並持久化到 DATADIR/auto.cnf 檔案裡。

transaction_id 是順序化的序列號(sequence number),在每臺 MySQL 伺服器上都是從 1 開始自增長的序列,是事務的唯一標識。例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:23

GTID 的集合(GTIDs)可以用 source_id+transaction_id 範圍表示,例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:1-18

複雜一點的:如果這組 GTIDs 來自不同的 source_id,各組 source_id 之間用逗號分隔;如果事務序號有多個範圍區間,各組範圍之間用冒號分隔,例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5:11-18,2C256447-3F0D-431B-9A12-575BB20C1507:1-27

5.3  GTID 如何產生
GTID 的生成受 gtid_next 控制。

在 Master 上,gtid_next 是預設的 AUTOMATIC,即 GTID 在每次事務提交時自動生成。它從當前已執行的 GTID 集合(即 gtid_executed)中,找一個大於 0 的未使用的最小值作為下個事務 GTID。同時將 GTID 寫入到 binlog(set gtid_next 記錄),在實際的更新事務記錄之前。

在 Slave 上,從 binlog 先讀取到主庫的 GTID(即 set gtid_next 記錄),而後執行的事務採用該 GTID。

5.4 GTID 相關的變數

GTID_EXECUTED

#表示已經在該例項上執行過的事務; 執行 RESET MASTER 會將該變數置空; 我們還可以通過設定 GTID_NEXT 在執行一個空事務,來影響 GTID_EXECUTED

GTID_PURGED

#已經被刪除了 binlog 的事務,它是 GTID_EXECUTED 的子集,只有在 GTID_EXECUTED 為空時才能設定該變數,修改 GTID_PURGED 會同時更新 GTID_EXECUTED 和 GTID_PURGED 的值。

GTID_OWNED

#表示正在執行的事務的 gtid 以及對應的執行緒 ID。

GTID_NEXT

#SESSION 級別變數,表示下一個將被使用的 GTID。

5.5 GTID 的工作原理

master 更新資料時,會在事務前產生 GTID,`一同記錄到 binlog 日誌中`。
slave 端的 i/o 執行緒將變更的 binlog,寫入到本地的 relay log 中,讀取值是根據`gitd_next變數`,告訴我們slave下一個執行哪個GTID。
sql 執行緒從 relay log 中獲取 GTID,然後對比 slave 端的 binlog 是否有記錄。
如果有記錄,說明該 GTID 的事務已經執行,slave 會忽略。
如果沒有記錄,slave 就會從 relay log 中執行該 GTID 的事務,並記錄到 binlog。
在解析過程中會判斷是否有主鍵,如果沒有二級索引就用全部掃描。

5.6 pos 與 GTID 有什麼區別

兩者都是日誌檔案裡事件的一個標誌,如果將整個 mysql 叢集看作一個整體,pos就是區域性的,GTID 就是全域性的.
mysql 節點的叢集,一主兩從,在 master,slave1,slave2 日誌檔案裡的 pos,都各不相同,就是一個 event,在 master 的日誌裡,pos 可能是 700,而在 slave1,slave2 裡,pos 可能就是 300,400 了,因為眾多 slave 也可能不是同時加入叢集的,不是從同一個位置進行同步.

而 GTID,在 master,slave1,slave2 各自的日誌檔案裡,同一個 event 的 GTID 值都是一樣的.

5.7 檢視binlog

檢視binlog列表

root@localhost : b:34: >show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |  15275772 |
+------------------+-----------+ 

檢視binlog的資訊

mysql-bin.000001 15275772 Gtid 141 15275837 SET @@SESSION.GTID_NEXT= '627a78ad-d67f-11ec-8d41-005056a6b4be:31'   //GTID
mysql-bin.000001 15275837 Query 141 15275900 BEGIN
mysql-bin.000001 15275900 Table_map 141 15275946 table_id: 111 (bi.t3)
mysql-bin.000001 15275946 Write_rows 141 15275999 table_id: 111 flags: STMT_END_F
mysql-bin.000001 15275999 Xid 141 15276030 COMMIT /* xid=120 */ 

5.8 event是什麼

二進位制日誌的最小記錄單位

對於DDL,DCL,一個語句就是一個event

對於DML語句來講:例如以下列子,就被分為了4個event

begin;

DML1

DML2

commit;

event的組成

開始位置(#at 157)+事件內容+結束位置(下一個#at 890,或者是end_log_pos 890)