一、binlog簡介:
1、什麼是binlog:
binlog日志用于記錄所有更新了資料或者已經潛在更新了資料(例如,沒有比對任何行的一個DELETE)的所有語句。語句以“事件”的形式儲存,它描述資料更改。
2、binlog的記錄格式:
Mysql binlog日志有三種格式,分别為:Statement ,MiXED ,和ROW;
(在MySQL5.7.7版本之後,把binlog_format的預設值修改成了ROW。master将修改表的event寫入binlog中,并且master将binlog資訊發送到slave,slave重放binlog中event。基于ROW格式複制是最安全的複制,slave需要的行鎖更少;但是也有一些缺點,那就是基于ROW格式的複制,binlog會記錄更多的資料。并且無法在slave上看到從master上擷取的語句,因為都是event。但是在ROW格式下,可以開啟binlog_rows_query_log_events參數,這會讓binlog在記錄events同時,也記錄原始的sql語句,以友善後續的查詢;)
①:Statement:每一條會修改資料的sql都會記錄在binlog中。
優點:不需要記錄每一行的變化,減少了binlog日志量,節約了IO,提高性能。(相比row能節約多少性能與日志量,這個取決于應用的SQL情況,正常同一條記錄修改或者插入row格式所産生的日志量還小于Statement産生的日志量,但是考慮到如果帶條件的update操作,以及整表删除,alter表等操作,ROW格式會産生大量日志,是以在考慮是否使用ROW格式日志時應該跟據應用的實際情況,其所産生的日志量會增加多少,以及帶來的IO性能問題。)
缺點:由于記錄的隻是執行語句,為了這些語句能在slave上正确運作,是以還必須記錄每條語句在執行的時候的一些相關資訊,以保證所有語句能在slave得到和在master端執行時候相同 的結果。另外mysql 的複制,像一些特定函數功能,slave可與master上要保持一緻會有很多相關問題(如sleep()函數, last_insert_id(),以及user-defined functions(udf)會出現問題).
使用以下函數的語句也無法被複制:
* LOAD_FILE()
* UUID()
* USER()
* FOUND_ROWS()
* SYSDATE() (除非啟動時啟用了 --sysdate-is-now 選項)
------同時在INSERT ...SELECT 會産生比 RBR 更多的行級鎖
②:Row: 不記錄sql語句上下文相關資訊,僅儲存哪條記錄被修改。
優點: binlog中可以不記錄執行的sql語句的上下文相關的資訊,僅需要記錄那一條記錄被修改成什麼了。是以row level的日志内容會非常清楚的記錄下每一行資料修改的細節。而且不會出現某些特定情況下的存儲過程,或function,以及trigger的調用和觸發無法被正确複制的問題
缺點: 所有的執行的語句當記錄到日志中的時候,都将以每行記錄的修改來記錄,這樣可能會産生大量的日志内容,比如一條update語句,修改多條記錄,則binlog中每一條修改都會有記錄,這樣造成binlog日志量會很大,特别是當執行alter table之類的語句的時候,由于表結構修改,每條記錄都發生改變,那麼該表每一條記錄都會記錄到日志中。
③:Mixedlevel: 是以上兩種level的混合使用,
一般的語句修改使用statment格式儲存binlog,如一些函數,statement無法完成主從複制的操作,則采用row格式儲存binlog,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日志形式,也就是在Statement和Row之間選擇一種.新版本的MySQL中隊row level模式也被做了優化,并不是所有的修改都會以row level來記錄,像遇到表結構變更的時候就會以statement模式來記錄。至于update或者delete等修改資料的語句,還是會記錄所有行的變更。
二、Binlog基本配制與格式設定
1、基本配制
Mysql BInlog日志格式可以通過mysql的my.cnf檔案的屬性binlog_format指定。如以下:
<code>binlog_format = ROW ---binlog日志格式</code>
<code>log_bin =</code><code>/mysql/mysql-bin</code><code>.log ---binlog日志名</code>
<code>expire_logs_days = 7 ---binlog過期清理時間</code>
<code>max_binlog_size 100m ---binlog每個日志檔案大小</code>
2.Binlog日志格式選擇
Mysql預設是使用Statement日志格式,推薦使用ROW.
由于一些特殊使用,可以考慮使用ROWED,如自己通過binlog日志來同步資料的修改,這樣會節省很多相關操作。對于binlog資料處理會變得非常輕松,相對mixed,解析也會很輕松(當然前提是增加的日志量所帶來的IO開銷在容忍的範圍内即可)。
3.mysqlbinlog格式選擇
mysql對于日志格式的標明原則:如果是采用 INSERT,UPDATE,DELETE 等直接操作表的情況,則日志格式根據 binlog_format 的設定而記錄,如果是采用 GRANT,REVOKE,SET PASSWORD 等管理語句來做的話,那麼無論如何 都采用 SBR 模式記錄。
三、binlog的相關參數:
<code>--log_bin:</code>
<code>設定此參數表示啟用binlog功能,并指定路徑名稱</code>
<code>--log_bin_index</code>
<code>設定此參數是指定二進制索引檔案的路徑與名稱</code>
<code>--binlog_do_db</code>
<code>此參數表示隻記錄指定資料庫的二進制日志</code>
<code>--binlog_ignore_db</code>
<code>此參數表示不記錄指定的資料庫的二進制日志</code>
<code>--max_binlog_cache_size</code>
<code>此參數表示binlog使用的記憶體最大的尺寸</code>
<code>--binlog_cache_size</code>
<code>此參數表示binlog使用的記憶體大小,可以通過狀态變量binlog_cache_use和binlog_cache_disk_use來幫助測試。</code>
<code> </code><code>binlog_cache_use:使用二進制日志緩存的事務數量</code>
<code> </code><code>binlog_cache_disk_use:使用二進制日志緩存但超過binlog_cache_size值并使用臨時檔案來儲存事務中的語句的事務數量</code>
<code>--max_binlog_size</code>
<code>Binlog最大值,最大和預設值是1GB,該設定并不能嚴格控制Binlog的大小,尤其是Binlog比較靠近最大值而又遇到一個比較大事務時,為了保證事務的完整性,不可能做切換日志的動作,隻能将該事務的所有SQL都記錄進目前日志,直到事務結束</code>
<code>--sync_binlog</code>
<code>這個參數直接影響mysql的性能和完整性</code>
<code>--sync_binlog=0:</code>
<code>當事務送出後,Mysql僅僅是将binlog_cache中的資料寫入Binlog檔案,但不執行fsync之類的磁盤 同步指令通知檔案系統将緩存重新整理到磁盤,而讓Filesystem自行決定什麼時候來做同步,這個是性能最好的。</code>
<code>--sync_binlog=n,在進行n次事務送出以後,Mysql将執行一次fsync之類的磁盤同步指令,同志檔案系統将Binlog檔案緩存重新整理到磁盤。</code>
<code>注意:Mysql中預設的設定是sync_binlog=0,即不作任何強制性的磁盤重新整理指令,這時性能是最好的,但風險也是最大的。一旦系統繃Crash,在檔案系統緩存中的所有Binlog資訊都會丢失</code>
四、binlog的删除:
binlog的删除可以手工删除或自動删除
1、自動删除binlog
<code>通過binlog參數(expire_logs_days )來實作mysql自動删除binlog</code>
<code>mysql> show binary logs;</code>
<code>mysql> show variables like </code><code>'expire_logs_days'</code><code>;</code>
<code>mysql> </code><code>set</code> <code>global expire_logs_days=3;</code>
2、手工删除binlog
<code>mysql> reset master; ----删除master的binlog</code>
<code>mysql> reset slave; ----删除slave的中繼日志</code>
<code>mysql> purge master logs before </code><code>'2017-03-30 17:20:00'</code><code>; -----删除指定日期以前的日志索引中binlog日志檔案</code>
<code>mysql> purge master logs to </code><code>'binlog.000002'</code><code>; ----删除指定日志檔案的日志索引中binlog日志檔案或者直接用作業系統指令直接删除</code>
<code>mysql> </code><code>set</code> <code>sql_log_bin=1</code><code>/0</code><code>; ----如果使用者有super權限,可以啟用或禁用目前會話的binlog記錄</code>
<code>mysql> show master logs; ---檢視master的binlog日志 </code>
<code>mysql> show binary logs; ---檢視master的binlog日志</code>
<code>mysql> show master status; ---用于提供master二進制日志檔案的狀态資訊</code>
<code>mysql> show slave hosts; ---顯示目前注冊的slave的清單。不以--report-host=slave_name選項為開頭的slave不會顯示在本清單中</code>
3、binglog的檢視
通過mysqlbinlog指令可以檢視binlog的内容
<code>[root@localhost ~]</code><code># mysqlbinlog /home/mysql/binlog/binlog.000003 | more</code>
<code>/*!40019 SET @@session.max_insert_delayed_threads=0*/;</code>
<code>/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;</code>
<code>DELIMITER /*!*/;</code>
<code># at 4</code>
<code>#120330 16:51:46 server id 1 end_log_pos 98 Start: binlog v 4, server v 5.0.45-log created 120330 1</code>
<code>6:51:46</code>
<code># Warning: this binlog was not closed properly. Most probably mysqld crashed writing it.</code>
<code># at 196</code>
<code>#120330 17:54:15 server id 1 end_log_pos 294 Query thread_id=3 exec_time=2 error_code=0</code>
<code>SET TIMESTAMP=1333101255/*!*/;</code>
<code>insert into tt7 </code><code>select</code> <code>* from tt7/*!*/;</code>
<code># at 294</code>
<code>#120330 17:54:46 server id 1 end_log_pos 388 Query thread_id=3 exec_time=28 error_code=0</code>
<code>SET TIMESTAMP=1333101286/*!*/;</code>
<code>alter table tt7 engine=innodb/*!*/;</code>
3.1、解析binlog格式
--位置
位于檔案中的位置,“at 196”說明“事件”的起點,是以第196位元組開始;“end_log_pos 294”說明以第294位元組結束
--時間戳
事件發生的時間戳:“120330 17:54:46”
--事件執行時間
事件執行花費的時間:"exec_time=28"
--錯誤碼
錯誤碼為:“error_code=0”
--伺服器的辨別
伺服器的辨別id:“server id 1”
注意:
1、binlog事件中的時間戳是從語句那裡繼承過來的,一條語句産生多個事件,那這些事件的時間戳都是一樣的,而且都是和第一個事件一緻的;
2、有時候我們會在binlog中發現執行語句和送出時間不一緻的情況,是因為有些事務是自動送出的,在這個事務中隻有一條語句執行了一定的時間;
innodb中rowid對binlog的影響:
1、在galera cluster上面最好不要讓一個事務更新太多的資料,可以适當控制在1萬行以内,都是麼有問題的,因為galera cluster的驗證和送出都是串行 的,一個事務太大,會導緻叢集其他事務都等待這個事務完成造成叢集假死現象;
2、在innodb中如果沒有指定主鍵,就會建立一個rowid,但是MySQL的binlog是server層,而innodb中的rowid是存儲引擎的東西,server層根本感覺不到 rowid的存在;
3、rowid是innodb自己定義的一個列,隻有在表中沒有定義主鍵的時候,系統才會給這個表加上這一列,但這一列隻是為了存儲,構成一個聚簇索引,但不 會暴露給邏輯層,并且上層也用不到它,是以直接忽略它即可;
4、在MySQL資料庫的使用中,一定要定義主鍵,如果沒有主鍵,并且是row模式的複制,就必然會造成這樣的問題,而不像其他資料庫一樣,如果沒有主鍵, 還可以使用rowid來操作表;
5、在galera cluster中,更要定義主鍵。如果沒有定義,必然會造成故障,這不是galera cluster的問題,隻是它會把這個問題放大而已;
本文轉自一個笨小孩51CTO部落格,原文連結http://blog.51cto.com/fengfeng688/1951160: ,如需轉載請自行聯系原作者