1.binlog日誌基本知識 MySQL的二進位日誌binlog可以說是MySQL最重要的日誌,它記錄了所有的DDL和DML語句(除了數據查詢語句select),以事件形式記錄,還包含語句所執行的消耗的時間。 binlog有三種格式:Statement、Row以及Mixed。分別是:基於SQL語句的 ...
1.binlog日誌基本知識
MySQL的二進位日誌binlog可以說是MySQL最重要的日誌,它記錄了所有的DDL和DML語句(除了數據查詢語句select),以事件形式記錄,還包含語句所執行的消耗的時間。
binlog有三種格式:Statement、Row以及Mixed。分別是:基於SQL語句的複製(statement-based replication,SBR)、 基於行的複製(row-based replication,RBR)和混合模式複製(mixed-based replication,MBR)。
格式 | 說明 | 優點 | 缺點 |
Statement模式 | 每一條會修改數據的sql語句都會記錄到binlog中。 | 不需要記錄每一行的變化,減少了binlog日誌量,節約了IO,提高性能。 | 缺點是在某些情況下會導致master-slave中的數據不一致(如sleep()函數,last_insert_id(),以及user-defined functions(udf)等會出現問題)。 |
Row模式 |
不記錄每條sql語句的上下文信息,僅需記錄哪條數據被修改了,修改成什麼樣了。 而且不會出現某些特定情況下的存儲過程、或function、或trigger的調用和觸發無法被正確複製的問題。 新版本的MySQL中對row level模式也被做了優化,並不是所有的修改都會以row level來記錄,像遇到表結構變更的時候就會以statement模式來記錄,如果sql語句確實就是update或者delete等修改數據的語句,那麼會記錄所有行的變更。 |
任何情況都可以被覆制,這對複製來說是最安全可靠的。多數情況下,從伺服器上的表如果有主鍵的話,複製就會快了很多。 |
binlog 大了很多 複雜的回滾時 binlog 中會包含大量的數據 主伺服器上執行 UPDATE 語句時,所有發生變化的記錄都會寫到 binlog 中,這會導致頻繁發生 binlog 的併發寫問題 UDF 產生的大 BLOB 值會導致複製變慢 無法從 binlog 中看到都複製了寫什麼語句 |
MIXED模式 | 實際上就是前兩種模式的結合,在mixed模式下,mysql會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式,也就是在statement和row之間選一種。 | 在Mixed模式下,一般的語句修改使用statment格式保存binlog,如一些函數,statement無法完成主從複製的操作,則採用row格式保存binlog,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式,也就是在Statement和Row之間選擇一種。 |
2.查看Row模式和Statement模式的binlog
為了加深印象,下麵我們看看兩者模式下的binlog到底長什麼樣子。
2.1 測試案例
分別在Row模式 和 Statement模式 下執行以下語句。
創建一張表
CREATE TABLE IF NOT EXISTS `tt` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(16) NOT NULL, `sex` enum('m','w') NOT NULL DEFAULT 'm', `age` tinyint(3) unsigned NOT NULL, `classid` char(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
向表中insert 5筆數據
insert into zyyshop.tt(`name`,`sex`,`age`,`classid`) values('yiyi','w',20,'cls1'),('xiaoer','m',22,'cls3'),('zhangsan','w',21,'cls5'),('lisi','m',20,'cls4'),('wangwu','w',26,'cls6');
用一條SQL語句修改前兩筆數據
update tt set name ='XXX' where id in (1,2);
在Row模式下形成的binlog文件為:mysql3306_bin.000011
在Statement模式下生成的binlog文件為:mysql3306_bin.000012。
2.2 用 show binlog events in 命令去查看分析2各個文件
查詢Row模式記錄如下:
查詢Statement模式記錄如下:
通過這個命令查看log,兩者差距不大。
2.3 通過mysqlbinlog命令解析
執行的命令分別如下
指定路徑/bin/mysqlbinlog --no-defaults --base64-output=decode-rows -v 指定路徑/mysql_log/mysql3306_bin.000011
指定路徑/bin/mysqlbinlog --no-defaults --base64-output=decode-rows -v 指定路徑/mysql_log/mysql3306_bin.000012
我們可以看到Row模式下的binlog記錄豐富的多,例如針對update的那條語句。
Row模式記錄如下:
Statement模式記錄如下:
總結:通過 show binlog events in 命令,查看 Row模式下記錄 和 Statement模式下的記錄,兩者基本一致。通過 mysqlbinlog 可以查看binlog具體的信息。Row模式下的binlog記錄比 Statement模式下豐富的多。
3. 通過 mysqlbinlog 和 grep 命令定位binlog文件中指定操作
既然binlog文件中有詳細的操作信息,如果有人誤操作,我們是否可以快速定位到對應操作信息呢?
快速定位可以幫助我們找到當時具體的操作是什麼,也可以找到POS(position)點,方便精準恢復。
例如,書接上回,我們發現表 tt 不在了,被人刪除了。ERROR 1146 (42S02): Table 'TestBinlog2.tt' doesn't exist。
那麼我們就可以在binlog查找drop相關的操作,命令如下:
指定路徑/bin/mysqlbinlog --no-defaults --base64-output=decode-rows -v 指定路徑/mysql_log/mysql3306_bin.000012 | grep drop
可惜沒有數據,這是什麼情況呢?不應該啊!!!
會不會大小寫的問題?那麼命令修改如下:
指定路徑/bin/mysqlbinlog --no-defaults --base64-output=decode-rows -v 指定路徑/mysql_log/mysql3306_bin.000012 | grep -i drop
找到了,但是信息不是很完整,我們可不可以找到,這條命令的更信息信息呢?例如,drop 前後各10條數據。
指定路徑/bin/mysqlbinlog --no-defaults --base64-output=decode-rows -v 指定路徑/mysql_log/mysql3306_bin.000012 | grep -i -A 10 -B 10 drop
這正是我們想要的,完美!
4. 其它知識補充
4.1 mysqlbinlog工具
此處主要講解用於查看binglog日誌的部分參數,用於還原binlog的參數在此不細講。
mysqlbinlog工具參數說明【用於查看的部分】 | |
參數 | 說明 |
-base64-output |
inlog輸出語句的base64解碼 分為三類: |
--verbose | 重新構建偽SQL語句的行信息輸出, -v會增加列類型的註釋信息。 |
--database=name | 列出資料庫的名稱(僅限binlog文件存儲在本地) |
4.2 grep 命令
grep是一個強大的文本搜索工具命令,用於查找文件中符合指定格式的字元串,支持正則表達式。
grep命令常用參數說明 | |
參數 | 說明 |
-A | 除了顯示符合條件的那一行之外,並顯示該列之後的指定行的內容內容。 |
-B | 除了顯示符合條件的那一行之外,並顯示該列之前的指定行的內容內容。 |
-c | 計算符合結果的行數。 |
-i | 忽略字元大小寫 |
-v | 反向查找 |
-e | 按指定字元串查找 |
-E | 按指定字元串指定的正則查找 |
-n | 在顯示符合條件的那一行前,標識出該行的行數標號。 |