MySQL複製的奇怪問題跟進

這是學習筆記的第 2034 篇文章微信


  在前幾天碰到了一個奇怪的複製問題,也作了簡單的跟蹤。併發

MySQL複製問題的分析高併發

沒想到今天在作壓力測試的時候,又碰到了相似的問題,這個問題的緊要程度要排上了日程。 學習

從binlog日誌的解析結果來看,是這樣的語句:測試

#190709 17:18:04 server id 182  end_log_pos 398120311 CRC32 0x89d5a523  Update_rows: table id 5252840 flags: STMT_END_Furl

### UPDATE `tbo_db`.`tda_data_20190709`spa

### WHERE.net

###   @1=749375136 /* LONGINT meta=0 nullable=0 is_null=0 */日誌

###   @2=7202 /* INT meta=0 nullable=0 is_null=0 */code

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

###   @4='2019-07-09 17:18:04' /* DATETIME(0) meta=0 nullable=0 is_null=0 */

###   @5='2019-07-09 17:18:04' /* DATETIME(0) meta=0 nullable=0 is_null=0 */

###   @6=0 /* LONGINT meta=0 nullable=0 is_null=0 */

### SET

###   @1=749375136 /* LONGINT meta=0 nullable=0 is_null=0 */

--

 這個語句乍一看有些不合邏輯,因此按照輸出的錯誤和問題發生的場景。以下的錯誤彷佛也有必定的道理。  

Could not execute Update_rows event on table tbo_db.tda_data_20190709; Can't find record in 'tda_data_20190709',

修復的過程是常規的思路,從主庫的binlog中解析獲得相關的偏移量位置附近的語句,而後評估是否能夠跳過,若是跳過則須要指向下一個GTID事務。 


我上次拋出了幾個問題,咱們來逐個作下驗證:

若是使用相似的語句,在MySQL主庫端會直接拋錯。

>>update test where id=100 and name='aa' set id=100;  

ERROR 1064 (42000):

而若是改成update,set,where的句式,語句能夠成功,儘管變動沒法匹配到相關數據,可是會生成相關的binlog,從庫的複製是正常的.

>>update test set id=100 , name='aa' where id=100;        

Query OK, 0 rows affected (0.00 sec)

咱們再來看一個案例,首先咱們看下數據狀況:

select * from test;

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

| id | name | memo1 |

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

|  1 | aa   | NULL  |

|  2 | bb   | NULL  |

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

2 rows in set (0.00 sec)

建表語句爲:

CREATE TABLE `test` (

  `id` int(11) NOT NULL,

  `name` varchar(30) DEFAULT NULL,

  `memo1` varchar(30) DEFAULT NULL,

  PRIMARY KEY (`id`),

  KEY `idx_name` (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

咱們接着使用正常的update作下變動。

>>update test set id=1  where id=1 and  name='aaa';

Query OK, 0 rows affected (0.00 sec)

這種狀況下的變動結果顯示爲0,可是依然是正常執行的。

而查看binlog的狀態,會發現生成的update語句也是正常的沒有作任何的改變。

#190709 23:37:57 server id 213  end_log_pos 149605040 CRC32 0xc6a341aa  Query   thread_id=288594        exec_time=0     error_code=0

SET TIMESTAMP=1562686677/*!*/;

update test set id=1  where id=1 and  name='aaa'

/*!*/;

# at 149605040

#190709 23:37:57 server id 213  end_log_pos 149605120 CRC32 0x22ffd3a3  Query   thread_id=288594        exec_time=0     error_code=0

SET TIMESTAMP=1562686677/*!*/;

到了這裏,咱們基本有一個總體的印象了。咱們再來回顧下那個update語句,會發現彷佛where和set子句的順序寫反了。

應該是update set xxxxx where xxxx

而順着這個思路往下思考,彷佛這個問題也就解釋的通了。 

對於我來講,對於這個問題的修復也是須要多方確認,首先須要排除應用端的一些高併發處理的異常狀況。 

同時在MySQL中查看是否存在一些相關的複製bug,這個問題還會持續跟進。



本文分享自微信公衆號 - 楊建榮的學習筆記(jianrong-notes)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索