【MySQL】你所不知道的行復制(binlog_format=row)
⒈ 本文目的:很多MySQL DBA 自認為對 mysql 的行復制有了很深刻的理解(這行復制不是初級 DBA 就該掌握的內容嘛,你怎麼提這麼低階的問題),那麼接下來可能會出乎你的意料。
⒉ 問題引出:
假設有A,B 兩個資料庫例項, A (主) ->B (從)
⑴ 第一問:
① 在主庫上建立表結構如下(特別注意這裡有唯一鍵,沒主鍵):
CREATE TABLE `test` (
`a` int(11) DEFAULT NULL,
`b` int(11) NOT NULL,
`c` varchar(20) DEFAULT NULL,
UNIQUE KEY `b_uique` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
② 我們在從庫B 上插入一條記錄:
insert into test values(2,2,'222');
③ 然後再主庫A 上插入一條記錄 :
insert into test values(3,2,'333');// 毫無疑問,從庫會出現 1032 的錯誤,唯一鍵衝突
然後再從庫上跳過一個事件( gtid 跳過一個事物); // 這樣主從複製 A->B 就會正常
④ 接下,我們在主庫A 上做一個操作:
update test set c='333ab' where b=2;
請回答 :B 庫主從是出現 1032 的錯誤呢,還是主從複製正常,如果正常,那麼 B 庫 test 表的資料是什麼?
⑵ 第二問:
① 在主庫上建立表結構如下(特別注意這裡有主鍵與唯一鍵):
CREATE TABLE `test1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `b` (`b`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4
② 我們在從庫B 上插入一條記錄:
insert into test values(2,2,2,'222');
③ 然後再主庫A 上插入一條記錄 :
insert into test values(3,2,2,'333');// 毫無疑問,從庫會出現 1032 的錯誤,唯一鍵衝突
然後再從庫上跳過一個事件( gtid 跳過一個事物); // 這樣主從複製 A->B 就會正常
④ 接下,我們在主庫A 上做一個操作:
update test set c='333ab' where b=2;
請回答: B 庫主從是出現 1032 的錯誤呢,還是主從複製正常,如果正常,那麼 B 庫 test 表的資料是什麼?
⒊ 問題分析與結論:
先別急著看答案,我們來看( 主庫 ) 解析 update 行復制 binlog 列印的是什麼?
BEGIN
/*!*/;
# at 4255
#190228 20:59:13 server id 212493307 end_log_pos 4307 CRC32 0x902463fc Table_map: `bcd`.`test1` mapped to number 340
# at 4307
#190228 20:59:13 server id 212493307 end_log_pos 4382 CRC32 0x06b71e7b Update_rows: table id 340 flags: STMT_END_F
### UPDATE `bcd`.`test1`
### WHERE
### @1=3 /* INT meta=0 nullable=0 is_null=0 */
### @2=3 /* INT meta=0 nullable=0 is_null=0 */
### @3=3 /* INT meta=0 nullable=0 is_null=0 */
### @4='33333' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */
### SET
### @1=3 /* INT meta=0 nullable=0 is_null=0 */
### @2=3 /* INT meta=0 nullable=0 is_null=0 */
### @3=3 /* INT meta=0 nullable=0 is_null=0 */
### @4='3aaa33' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */
# at 4382
#190228 20:59:13 server id 212493307 end_log_pos 4413 CRC32 0x9b13368e Xid = 14175
COMMIT/*!*/;
沒錯,他記錄了
原來行的內容,這裡原來行是
(3,3,3,'33333')
然後被改成了
(3,3,3,'3aaa33');
那麼這條binlog 被複制到從庫後,就涉及到如何定位一行進行修改的問題了:
是透過(3,3,3,'33333' )所有元組定位一行嗎?是透過主鍵唯一鍵 (3,3) 定位一行嗎?是透過主鍵 (3) 定位一行嗎?是透過唯一鍵 (3) 定位一行嗎?
其實統統都不是,從庫定位一行如下:
當表中有主鍵時,則透過主鍵定位一行
當表中同時有主鍵與唯一鍵時,則透過主鍵定位一行;主鍵不同,唯一鍵相同,代表的是不同行
當表只有唯一鍵是,則透過唯一鍵定位一行
系統自動生成的主鍵,不參與複製,不能定位一行
那麼上面的問題,各位看官可以答出來了嗎?
問題一:B 庫不會出現 1032 的錯誤,最終從庫 B 的資料是 (3,2,'333ab')
問題二:B 庫會出現 1032 的錯誤,最終 B 庫的資料是 (2,2,2,'222')
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30221425/viewspace-2637246/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 你所不知道的cssCSS
- 你所不知道的 POST
- 你所不知道的 Transformer!ORM
- 你所不知道的JavaScript(三)JavaScript
- 你所不知道的XML安全XML
- 你所不知道的JavaScript 二JavaScript
- 你所不知道的 AI 進展AI
- 提升----你所不知道的JavaScript系列(3)JavaScript
- Python: 你所不知道的星號 * 用法Python
- MySQL裡的found_row()與row_count()MySql
- 閉包—-你所不知道的JavaScript系列(4)JavaScript
- Python中你所不知道的“隱藏技巧”!Python
- 你所不知道的 C# 10新特性C#
- JavaScript中你所不知道的陣列ArrayBufferJavaScript陣列
- 你所不知道的跨域資源共享(CORS)跨域CORS
- 關於HTTP/3背後你所不知道的HTTP
- 你所不知道的阿里開源那些事兒阿里
- 你所不知道的 Chrome 控制檯除錯技巧Chrome除錯
- 你所不知道的Java效能優化之String!Java優化
- 你所不知道的Python | 字串連線的祕密Python字串
- 你所不知道的js的小知識點(1)JS
- 你所不知道的 Typescript 與 Redux 型別優化TypeScriptRedux型別優化
- 你所不知道的 CSS 陰影技巧與細節CSS
- 五個你所不知道的Flutter開發細節Flutter
- 你所不知道的Typescript與Redux型別優化TypeScriptRedux型別優化
- 你所不知道的 Python 冷知識!(建議收藏)Python
- 效能測試工具Jmeter你所不知道的內幕JMeter
- 效能測試工具LoadRunner你所不知道的內幕
- 你所不知道的 Python 冷知識!(二)(建議收藏)Python
- 你所不知道的AWS 雲服務清單(71種)
- 你所不知道的ASP.NET Core進階系列(三)ASP.NET
- 你所不知道的Python | 函式引數的演進之路Python函式
- 你所不知道的Python | 字串格式化的演進之路Python字串格式化
- 你所不知道的用 less 檢視檔案的高階用法
- 你所不知道的前端效能優化不完全手冊前端優化
- ios蘋果企業賬號你所不知道的那些點iOS蘋果
- 關於JavaScript物件,你所不知道的事(一)- 先談物件JavaScript物件
- 你不知道的瀏覽器頁面渲染機制瀏覽器