您好,登錄后才能下訂單哦!
如何淺析MySQL中的binlog和redo,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
有一個小問題可能很多人都想起過,那就是MySQL中既然已經(jīng)有了binlog,為什么還需要redo,這個問題看起來好像很簡單,但是細細品來,還是有不少值得注意的地方。
對于數(shù)據(jù)恢復(fù),尤其是異常宕機的情況下,再次啟動的時候,如何恢復(fù),恢復(fù)的數(shù)據(jù)依據(jù),這個尤為重要,在MySQL中是有checkpoint的技術(shù)來做一個基本的檢查點控制,也就是常說的LSN,對于事務(wù)性數(shù)據(jù)庫,大都會采用write ahead log的策略,即當前事務(wù)提交的時候,先寫redo,在修改相應(yīng)的頁,如果發(fā)生宕機導(dǎo)致數(shù)據(jù)丟失的時候,可以通過重做日志來完成數(shù)據(jù)的恢復(fù),但是MySQL和其它有些數(shù)據(jù)庫有些特別的是這個binlog,它不是采用checkpoint的實現(xiàn)方式,我們可以設(shè)想這樣一個情況,一個事務(wù)提交的時候,信息會寫入redo,而在這個操作的過程中,其實binlog的寫入也是同步的,如果redo的信息在redo log buffer中可能還沒有刷新到磁盤中,出現(xiàn)宕機的情況,就可能導(dǎo)致從庫的數(shù)據(jù)已經(jīng)應(yīng)用了binlog傳輸?shù)臄?shù)據(jù)變化,而redo中還沒來得及提交,這可能就會有數(shù)據(jù)不一致的情況發(fā)生,如果在異常狀態(tài)下啟動數(shù)據(jù)庫就會開啟數(shù)據(jù)恢復(fù)的模式,可能從庫的數(shù)據(jù)就會出現(xiàn)不一致。
這種情況聽起來有些特別,但是對于我們理解redo和binlog的問題蠻有幫助,我們來做一個測試吧,僅僅在測試環(huán)境中進行調(diào)試所用。
首先為了減少數(shù)據(jù)的變更影響,我們先做一個flush logs的操作,盡可能保留少,數(shù)據(jù)變化新的日志內(nèi)容
在主庫端切換日志:
flush logs;
查看binlog的情況,使用show master status或者show binary logs都可以。
mysql> show master status\G
*************************** 1. row ***************************
File: binlog.000014
Position: 230
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 1bb1b861-f776-11e6-be42-782bcb377193:1,
25ee7482-07cd-11e7-a40c-0026b935eb76:1-1502468
1 row in set (0.00 sec)
我們得到mysql服務(wù)的進程號。
# ps -ef|grep -w mysqld|grep -v grep|awk '{print $2}'
1751
我們創(chuàng)建一個表test 字段為id和name(id int ,name varchar(20))
已經(jīng)存在4條數(shù)據(jù)如下:
mysql> select *from test.test;
+------+------+
| id | name |
+------+------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
| 4 | dd |
+------+------+
4 rows in set (0.00 sec)
從庫 查看數(shù)據(jù)和主庫此時是同步的。這是我們測試的一個基礎(chǔ)。
我們可以通過gdb的方式進行簡單調(diào)試。
# gdb -p 1751
就馬上進入了調(diào)試模式,我們可以設(shè)置一個斷點。
我們在設(shè)置斷點之前先插入2條數(shù)據(jù),從庫此時也是5條數(shù)據(jù)。
mysql> insert into test values(5,'ee');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(6,'ff');
Query OK, 1 row affected (0.00 sec)
然后設(shè)置斷點,這是關(guān)鍵所在。
(gdb) b MYSQL_BIN_LOG::process_commit_stage_queue
Breakpoint
1 at 0xec73ca: file
/export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/binlog.cc,
line 8430. (2 locations)
然后在主庫嘗試插入一條記錄
insert into test values(7,'gg');
毫無疑問,這條語句會hang住。因為我們的斷點就在提交的時候。
這個時候我們前進一小步,使用c即continue
(gdb) c
Continuing.
[Switching to Thread 0x409c0940 (LWP 1798)]
Breakpoint 1, MYSQL_BIN_LOG::process_commit_stage_queue (this=0x1e8ba00, thd=0xec254e0, first=0xec254e0)
at /export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/binlog.cc:8430
8430 /export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/binlog.cc: No such file or directory.
in /export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/binlog.cc
這個時候那條SQL語句依舊是hang的狀態(tài),但是可以看出堆棧,binlog是寫入完成了
從庫此時是應(yīng)用了數(shù)據(jù)變更,此時是7條數(shù)據(jù)。
我們也可以抓取一下binlog,看看里面是否已經(jīng)寫入了數(shù)據(jù)。
[root@grtest s1]# /usr/local/mysql/bin/mysqlbinlog -vv binlog.0000014
可以明顯看到這樣的語句:
...
BINLOG '
DK3KWBPqDAAALgAAAHcDAAAAAOUAAAAAAAEABHRlc3QABHRlc3QAAgMPAhQAAw==
DK3KWB7qDAAAJwAAAJ4DAAAAAOUAAAAAAAEAAgAC//wHAAAAAmdn
'/*!*/;
### INSERT INTO `test`.`test`
### SET
### @1=7 /* INT meta=0 nullable=1 is_null=0 */
### @2='gg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */
# at 926
#170316 23:19:40 server id 3306 end_log_pos 953 Xid = 55
COMMIT/*!*/;
我們此時模擬宕機的情況,殺掉進程
kill -9 1751 29617
然后把binlog改個名字,關(guān)閉log_bin
[root@grtest s1]# mv binlog.000014 binlog.000014.bak
再次啟動之后,就會發(fā)現(xiàn)此時的主庫中數(shù)據(jù)還是6條,而從庫卻是7條。
而如果我們把binlog改回來,開啟log_bin并啟動主庫
mv binlog.000014.bak binlog.000014
然后再次查看數(shù)據(jù),就會發(fā)現(xiàn)主從庫此時的數(shù)據(jù)竟然不同。從庫的數(shù)據(jù)明顯要多,這也就從一個側(cè)面映射了我們開始的一個設(shè)想,在異常宕機的情況下,redo的數(shù)據(jù)還沒有刷新到redo文件中,此時已經(jīng)寫入了binlog,這樣就在這樣一個臨界點導(dǎo)致了主從數(shù)據(jù)的不一致。
當然我是使用一個調(diào)試的態(tài)度來做的測試,里面還有很多技巧需要鞏固。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。