1. 程式人生 > >MySQL——binlog

MySQL——binlog

mysql binlog

一、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指定。如以下:

binlog_format = ROW             ---binlog日誌格式
log_bin =/mysql/mysql-bin.log        ---binlog日誌名
expire_logs_days = 7            ---binlog過期清理時間
max_binlog_size 100m            ---binlog每個日誌文件大小

2.Binlog日誌格式選擇


Mysql默認是使用Statement日誌格式,推薦使用ROW.


由於一些特殊使用,可以考慮使用ROWED,如自己通過binlog日誌來同步數據的修改,這樣會節省很多相關操作。對於binlog數據處理會變得非常輕松,相對mixed,解析也會很輕松(當然前提是增加的日誌量所帶來的IO開銷在容忍的範圍內即可)。


3.mysqlbinlog格式選擇


mysql對於日誌格式的選定原則:如果是采用 INSERT,UPDATE,DELETE 等直接操作表的情況,則日誌格式根據 binlog_format 的設定而記錄,如果是采用 GRANT,REVOKE,SET PASSWORD 等管理語句來做的話,那麽無論如何 都采用 SBR 模式記錄。



三、binlog的相關參數:

--log_bin:
設置此參數表示啟用binlog功能,並指定路徑名稱

--log_bin_index
設置此參數是指定二進制索引文件的路徑與名稱

--binlog_do_db
此參數表示只記錄指定數據庫的二進制日誌

--binlog_ignore_db
此參數表示不記錄指定的數據庫的二進制日誌

--max_binlog_cache_size
此參數表示binlog使用的內存最大的尺寸

--binlog_cache_size
此參數表示binlog使用的內存大小,可以通過狀態變量binlog_cache_use和binlog_cache_disk_use來幫助測試。
    binlog_cache_use:使用二進制日誌緩存的事務數量
    binlog_cache_disk_use:使用二進制日誌緩存但超過binlog_cache_size值並使用臨時文件來保存事務中的語句的事務數量

--max_binlog_size
Binlog最大值,最大和默認值是1GB,該設置並不能嚴格控制Binlog的大小,尤其是Binlog比較靠近最大值而又遇到一個比較大事務時,為了保證事務的完整性,不可能做切換日誌的動作,只能將該事務的所有SQL都記錄進當前日誌,直到事務結束

--sync_binlog
這個參數直接影響mysql的性能和完整性

--sync_binlog=0:
當事務提交後,Mysql僅僅是將binlog_cache中的數據寫入Binlog文件,但不執行fsync之類的磁盤        同步指令通知文件系統將緩存刷新到磁盤,而讓Filesystem自行決定什麽時候來做同步,這個是性能最好的。

--sync_binlog=n,在進行n次事務提交以後,Mysql將執行一次fsync之類的磁盤同步指令,同誌文件系統將Binlog文件緩存刷新到磁盤。
註意:Mysql中默認的設置是sync_binlog=0,即不作任何強制性的磁盤刷新指令,這時性能是最好的,但風險也是最大的。一旦系統繃Crash,在文件系統緩存中的所有Binlog信息都會丟失


四、binlog的刪除:

binlog的刪除可以手工刪除或自動刪除


1、自動刪除binlog

通過binlog參數(expire_logs_days )來實現mysql自動刪除binlog
mysql> show binary logs;
mysql> show variables like ‘expire_logs_days‘;
mysql> set global expire_logs_days=3;


2、手工刪除binlog

mysql> reset master;       ----刪除master的binlog
mysql> reset slave;        ----刪除slave的中繼日誌
mysql> purge master logs before ‘2017-03-30 17:20:00‘;   -----刪除指定日期以前的日誌索引中binlog日誌文件
mysql> purge master logs to ‘binlog.000002‘;     ----刪除指定日誌文件的日誌索引中binlog日誌文件或者直接用操作系統命令直接刪除
mysql> set sql_log_bin=1/0;    ----如果用戶有super權限,可以啟用或禁用當前會話的binlog記錄
mysql> show master logs;     ---查看master的binlog日誌 
mysql> show binary logs;     ---查看master的binlog日誌
mysql> show master status;   ---用於提供master二進制日誌文件的狀態信息
mysql> show slave hosts;     ---顯示當前註冊的slave的列表。不以--report-host=slave_name選項為開頭的slave不會顯示在本列表中


3、binglog的查看

通過mysqlbinlog命令可以查看binlog的內容

[[email protected] ~]# mysqlbinlog  /home/mysql/binlog/binlog.000003  | more
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#120330 16:51:46 server id 1  end_log_pos 98    Start: binlog v 4, server v 5.0.45-log created 120330 1
6:51:46
# Warning: this binlog was not closed properly. Most probably mysqld crashed writing it.
# at 196
#120330 17:54:15 server id 1  end_log_pos 294   Query   thread_id=3     exec_time=2     error_code=0
SET TIMESTAMP=1333101255/*!*/;
insert into tt7 select * from tt7/*!*/;
# at 294
#120330 17:54:46 server id 1  end_log_pos 388   Query   thread_id=3     exec_time=28    error_code=0
SET TIMESTAMP=1333101286/*!*/;
alter table tt7 engine=innodb/*!*/;


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的問題,只是它會把這個問題放大而已;


本文出自 “笨小孩的dba之路” 博客,請務必保留此出處http://fengfeng688.blog.51cto.com/4896812/1951160

MySQL——binlog