成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL:主從HASH SCAN算法可能導(dǎo)致從庫數(shù)據(jù)錯誤

數(shù)據(jù)庫 MySQL
本文主要以hash scan全表為基礎(chǔ)進行分析,而不涉及到hash scan索引,實際上都會遇到這個問題。

本文主要以hash scan全表為基礎(chǔ)進行分析,而不涉及到hash scan索引,實際上都會遇到這個問題。本文主要描述的是update event,delete event也是一樣的,測試包含8022,8026,8028均包含這個問題。

約定:bi為update row event的before image

一、問題描述

這里簡單看一下報錯的我們直接用metalink 上的文章來看,實際上作為做oracle的老人,還是比較查metalink的,在metalink上也有一些MySQL相關(guān)的文章,但是很少,如下:

錯誤就是那個錯誤,解決辦法也比較簡單就是加上主鍵重做,這個問題我個人已經(jīng)遇到N次了,每次都這么處理的,隱約的覺得hash scan 有BUG。

二、關(guān)于hash scan算法簡介

在8.0中 hash scan 使用一個std::unordered_multimap的hash容器,記錄其key - value值,每個key - value 代表修改的一行值,因為multimap容器允許重復(fù)的key - value,因此可以存在相同的行記錄,這和5.7的實現(xiàn)不同,5.7是自己寫的,而8.0 用的容器。其中:

  • key為當(dāng)前表中根據(jù)每個字段計算出來的crc32值,句函數(shù)為Hash_slave_rows::make_hash_key,也就是checksum_crc32函數(shù)
  • value為當(dāng)前本行在event buffer中的位置,也就是指向?qū)嶋H的數(shù)據(jù)。

當(dāng)然這里是簡化了,實際value還包含一個std::unordered_multimap的迭代器和刪除器,其中迭代器的作用是通過相同的key 調(diào)用,std::next 來查找下一個相同key的記錄。 

當(dāng)一個event掃描結(jié)束后會將所有這個event的記錄存儲到這個hash容器中,函數(shù)Hash_slave_rows::put。而查找階段會全表掃描本表,每次獲取一行數(shù)據(jù),然后在hash容器中進行查找,并進行處理,如下:

->循環(huán)1 讀取表中的每條數(shù)據(jù)
  計算本行數(shù)據(jù)的crc32值,并且在event的hash 結(jié)構(gòu)查找對應(yīng)的entry
  ->循環(huán)2 
    拷貝讀取到的行從record0到record1,也就是record1為掃描到的行
    ->循環(huán)3 
      從查找的entry中獲取bi記錄的位置,并且放入到record0中
      比對record0和record1的值是否相等,也就是record0是event對應(yīng)的bi數(shù)據(jù),而record1是掃描的本行數(shù)據(jù)
      如果比對不成功這獲取查找到entry key在event中的下一條記錄
    <-循環(huán)3結(jié)束條件為退出條件為找到了一條匹配記錄或者entry為NULL
    ->如果查找到對應(yīng)的entry且比對成功,也就是entry不為NULL
      恢復(fù)record1到record0中
      并且刪除hash 結(jié)構(gòu)中的這個entry
      進行數(shù)據(jù)修改
  <-循環(huán)2結(jié)束條件為再次使用record0也就是掃描的行在event的hash結(jié)構(gòu)查找不到對應(yīng)的entry,很顯然后面邏輯只要匹配到了就會就會從event的hash結(jié)構(gòu)查找中刪除掉    

這樣做的目的很明確就是將全表掃描的次數(shù)減少,每個event才做一次,這樣自然提高了性能。

三、BUG登場

這個BUG是同事查詢到后給我的,BUG如下:https://bugs.mysql.com/bug.php?id=101828

在這個BUG中,出現(xiàn)了2行記錄crc32一致的情況,如下2個字符串的crc32也是一致的:

mysql> select crc32("b5a7b602ab754d7ab30fb42c4fb28d82");
+-------------------------------------------+
| crc32("b5a7b602ab754d7ab30fb42c4fb28d82") |
+-------------------------------------------+
|                                2575120314 |
+-------------------------------------------+
1 row in set (3.16 sec)

mysql> select crc32("d19f2e9e82d14b96be4fa12b8a27ee9f");
+-------------------------------------------+
| crc32("d19f2e9e82d14b96be4fa12b8a27ee9f") |
+-------------------------------------------+
|                                2575120314 |
+-------------------------------------------+

但是在整個hash scan 邏輯中,實際上比對crc32相同過后還是做了實際值的比較,也就是不完全依賴crc32值。這個BUG的流程如下:

第一階段,數(shù)據(jù)準(zhǔn)備階段:

CREATE TABLE t1 (
  a bigint unsigned not null,
  b bigint unsigned not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into t1 values(0xa8e8ee744ced7ca8, 0x6850119e455ee4ed),(0x135cd25c170db910, 0x6916c5057592c796);

這兩行數(shù)據(jù)的crc32值一樣。

第二階段,數(shù)據(jù)錯誤階段 主庫執(zhí)行:

update t1 set a=1 where a=0x135cd25c170db910 and b=0x6916c5057592c796;

顯然這條語句更改是第二行數(shù)據(jù),但是到了從庫由于BUG存在更改的是第一條數(shù)據(jù),這個時候數(shù)據(jù)已經(jīng)錯誤了。這個時候主庫數(shù)據(jù)如下:

mysql> select * from t1;
+----------------------+---------------------+
| a                    | b                   |
+----------------------+---------------------+
| 12171240176243014824 | 7516527149547709677 |
|                    1 | 7572456450708129686 |
+----------------------+---------------------+
2 rows in set (0.00 sec)

從庫數(shù)據(jù)如下:

mysql> select * from t1;
+---------------------+---------------------+
| a                   | b                   |
+---------------------+---------------------+
|                   1 | 7516527149547709677 |
| 1395221277543610640 | 7572456450708129686 |
+---------------------+---------------------+
2 rows in set (0.00 sec)

第三階段,報錯階段:

update t1 set a=2 where a=1;

這里主庫修改是第二行記錄,也就是:

a=1
b=7572456450708129686

但是到了從庫,因為a=1和b=7572456450708129686的hash crc32值和表中任何一個記錄都不匹配 ,這報錯。

四、原因

來看一下為什么出現(xiàn)問題。 在例子中如果我們修改了1行數(shù)據(jù),并且這行數(shù)據(jù)在表中有2數(shù)據(jù)存在相同的crc32值,主庫修改的是2行數(shù)據(jù),那么可能存在下面的問題:

從庫首先在循環(huán)1中獲取第1行數(shù)據(jù),然后在hash結(jié)構(gòu)中查找,找到相同的crc32值,進入循環(huán)2拷貝record后進入循環(huán)3首先對比record0到record1的值也就是event中的數(shù)據(jù),也就是第2行數(shù)據(jù)和第1行數(shù)據(jù)對比,顯然實際的值肯定不同,這獲取event相同crc32的下一條記錄,顯然不存在因為就更改了1條數(shù)據(jù),返回為NULL,循環(huán)3結(jié)束,繼續(xù),因為entry為NULL,恢復(fù)record0的操作和更改數(shù)據(jù)的操作都不會做。

然后循環(huán)2循環(huán)條件再次通過掃描到的行數(shù)據(jù)查找hash結(jié)構(gòu)的entry依舊是第1行數(shù)據(jù)的entry,進行下一次循環(huán),這個時候因為record0沒有恢復(fù),還是event對應(yīng)的bi數(shù)據(jù),因此拷貝后record1也就是event對應(yīng)的bi數(shù)據(jù),接著進入循環(huán)3,這個時候進行比較,實際上比較都是event中的數(shù)據(jù),因此比較一定成功,進入修改流程。 這個時候?qū)嶋H上就是把表中的第一行數(shù)據(jù)給修改了。也就是這個時候數(shù)據(jù)已經(jīng)不對了,再次進行修改在錯誤數(shù)據(jù)上進行修改自然就可能查不到數(shù)據(jù)的情況。這實際就是一個crc32碰撞后邏輯錯誤導(dǎo)致的問題。

五、總結(jié)

  • 數(shù)據(jù)量和本BUG相關(guān),如果數(shù)據(jù)量大則crc32 不同記錄產(chǎn)生相同crc32的可能性就高一些。
  • 本BUG一直未修復(fù),BUG提交者提交了patch,實際上就是當(dāng)entry為NULL的時候結(jié)束循環(huán)2,這樣就會掃描表的下一條數(shù)據(jù),而不是直接修改本行數(shù)據(jù)。不知道官方是否覺得BUG中提交的patch不合適,還是其他原因。
  • 這個BUG看起來和Bug#28846386: RBR + STORED FUNCTION WITHOUT PRIMARY KEY - CAN'T FIND RECORD IN 有關(guān),可能是修復(fù)一個BUG引入的新的BUG,這是8017修復(fù)的。
  • 8.0 hash scan 已經(jīng)成為了默認(rèn)的算法,因此概率大大提高。
  • 看來主鍵越來越重要了,有主鍵自然不會觸發(fā)這個問題,還是重要事情說三遍吧,加主鍵、加主鍵、加主鍵。
責(zé)任編輯:趙寧寧 來源: MySQL學(xué)習(xí)
相關(guān)推薦

2011-04-14 11:09:14

MySQL數(shù)據(jù)庫

2021-05-11 10:18:07

數(shù)據(jù)泄露云安全云計算

2011-08-29 14:00:26

MySQL主從延時

2021-05-19 08:21:09

MySQL數(shù)據(jù)庫GTID

2020-08-12 08:25:43

數(shù)據(jù)庫MySQL技術(shù)

2018-01-04 10:08:08

2013-01-14 13:39:22

Windows 8Linux

2023-09-05 19:50:03

2017-01-17 15:14:49

MySQL數(shù)據(jù)庫自動化

2024-11-28 09:23:09

2010-10-15 16:03:03

Mysql分表處理

2022-04-18 09:31:21

數(shù)據(jù)庫查詢MySQL

2016-03-29 10:21:24

大數(shù)據(jù)數(shù)據(jù)分析數(shù)據(jù)管理

2018-09-04 05:05:57

2024-08-12 15:26:42

2023-09-08 00:12:40

2011-04-06 09:59:00

MySQL數(shù)據(jù)庫主從復(fù)制

2010-11-03 08:41:55

MySQL

2023-12-11 07:44:36

MySQL架構(gòu)高可用

2024-10-21 08:21:12

數(shù)據(jù)庫主從延遲
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日韩精品一区二区三区 | 少妇黄色| 中文字幕av在线 | 久久久久免费精品国产小说色大师 | 69电影网| 欧美日韩一区二区三区视频 | 亚洲黄色在线 | 国产午夜高清 | 五月天综合影院 | 久久草在线视频 | 色综合久 | 亚洲精品视频在线 | 翔田千里一区二区 | 欧美日韩亚洲二区 | 国产精品视频一二三区 | 国产在线看片 | 亚洲精品一区二区三区蜜桃久 | 成人免费观看男女羞羞视频 | 一级黄色片网址 | 九九热在线免费视频 | 精品一区二区久久久久久久网站 | 日韩在线观看网站 | 91网站在线播放 | 国产精品美女久久久久久免费 | 亚洲一区二区三区免费在线观看 | 亚洲成人网在线播放 | 亚洲丝袜天堂 | 8x国产精品视频一区二区 | 中文字幕视频在线免费 | 91午夜在线 | 午夜影院在线观看免费 | 色综合天天天天做夜夜夜夜做 | 国产日韩欧美 | 国产黄色网址在线观看 | 欧美亚洲高清 | 一区二区视频 | 国产成人小视频 | 一级久久久久久 | a级片在线观看 | 精品三区 | 亚洲国产精品人人爽夜夜爽 |