MySQL學習之二進制日誌

進制日誌記錄了數據庫的所有改變,使得任何Slave都可以通過執行Master二進制日誌保持數據的一致。

二進制日誌僅包含可能改變數據庫的語句。那些尚沒有但是可能改變數據庫的語句也會記錄下來,注意那些可能帶來變化的語句,如DROP TABLE IFEXISTS CREATE IF NOT EXISTS,以及那些不匹配任何行的語句,select語句一般不會被記錄,因爲它們不會對數據庫做任何改動。

服務器上的事務通常不是一個接一個順序執行的,而是交錯的並行執行,爲了防止兩個事務之間產生衝突導致不一致的結果,服務器要確保事務的執行是順序化的。二進制日誌按Master上的提交順序記錄事務,雖然事務可能在Master上交錯執行,但每個事務在二進制日誌中的順序是不變的,取決於事務的提交(commit)時間。


二進制日誌的結構


wKioL1Q-bhvz628zAADCAobzMzM496.jpg

看上圖,二進制日誌由若干個文件組成,事件存儲在一系列binlog文件中,文件名類似於host-bin.000001,還有一個索引文件通常文件名爲host-bin.index,索引文件跟蹤服務器使用的所以binlog文件,索引文件的每一行都包含了一個binlog文件的完整文件名,使用這些命令,如PURGE BINARY LOGSRESTART MASTER FLUSH LOGS,添加或刪除binlog文件,也導致索引文件添加或刪除行。


數據安全

    比較常見的敏感信息就是密碼,當執行改變數據庫中表的語句,並且它包含訪問這個表所必須的密碼的時候,包含密碼的事件就會被寫入二進制日誌。

例:

       update employee set pass= password(‘123456’) where email = ‘[email protected]’;

    如果複製是正確的,最好重寫這個語句,可以通過以下方法實現:計算和存儲哈希密碼到用戶自定義變量,然後在表達式中使用它:

       set @password =password(‘123456’);

       update employee set pass= @password  where email = ‘[email protected]’;

    由於set語句沒有被複制,密碼將不會存儲在二進制日誌中,而僅在執行該語句的時候存儲在服務器內存中。


清除binlog文件

隨着時間的推移,服務器會集聚binlog文件,要使服務器自動清理舊的binlog文件,需設置expire-logs-days選項。這個選項可用來作爲一個服務器變量,達到你想保留binlog文件的天數,如果希望在重啓後仍保持自動清除,必須添加該設置到my.cnf文件。

使用PURGE BINARY LOGS 命令手工清除binlog文件,有如下兩種格式:

PURGE BINARYLOGS BEFORE datetime

這個命令格式將清除在給定時間之前的所有binlog文件。如果datetime在一個日誌文件的中間,那麼datetime所在的那個文件之前的所有文件將被清除。

實戰演練:

1、由於是通過日期時間刪除,我們先要知道需要刪除那個時間之前的二進制日誌。

mysqlbinlog  --force-if-open--base64-output=never mysql-bin.000003

wKioL1Q-byHyk5DoAAJv_OFARIo967.jpg

2、假如我們需要刪除2014/09/09之前的日誌,執行如下命令:

PURGE BINARY LOGS BEFORE 140909

wKiom1Q-b2ahjwdVAAJM8b2znxw457.jpg

PURGE BINARY LOGS TO ‘filename’

這個命令格式將清除在給定文件之前的所有文件。也就是Show master logs 命令輸出的所有文件中,在filename之前的文件都將被刪除。

實戰演練:

PURGE BINARY LOGS TO 'mysql-bin.000002';

wKioL1Q-b96x3XpCAAGBmvM3Ujg201.jpg


mysqlbinlog 工具的使用

mysqlbinlog

       --short-form 只打印被執行的SQL語句信息,忽略關於二進制日誌的事件註釋信息。

       --force-if-open 如果binlog文件正在被寫入,或因爲服務器崩潰,mysqlbinlog都將打印一條警告信息說這個binlog文件沒有被正確關閉,這個選項忽略打印警告信息。

       --base64-output=never  阻止mysqlbinlog打印base64-encoded事件。

       start-position=bytepos 轉儲的第一個事件的字節位置。如果幾個binlog是提供給mysqlbinlog的,這個位置將被解釋爲在序列號中第一個文件的位置。

       stop-position=bytepos 最後打印的事件的字節位置,如果給定了多個binlog文件,該位置將是序列中最後一個文件的位置。

       start-datetime=datetime 只打印那些有時間戳或datetime後的事件。

       stop-datetime=datetime 只打印那些有時間戳或datetime前的事件。

讀取遠程文件實例:

       mysqlbinlog  --read-from-remote-server --host=192.168.18.202 --base64-output=never --user=repl_user --password --start-position=386 --stop-position=643 mysqld-bin.000001


我們接下來使用mysqlbinlog來讀取一個二進制日誌文件:

mysqlbinlog --force-if-open--base64-output=never /mylogbin/mysql-bin.000001 | cat -n

 

     1    /*!50530 SET@@SESSION.PSEUDO_SLAVE_MODE=1*/;

     2    /*!40019SET @@session.max_insert_delayed_threads=0*/;

     3    /*!50003SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;

     4    DELIMITER/*!*/;

     5    #at 4

     6    #141015  9:03:53 server id 1  end_log_pos 245      Start: binlog v 4, server v 5.5.32-MariaDB-log created141015  9:03:53 at startup

     7    ROLLBACK/*!*/;

     8    #at 245

     9    #141015  9:09:21 server id 1  end_log_pos 428      Query     thread_id=1    exec_time=0   error_code=0

    10    use`test`/*!*/;

    11    SETTIMESTAMP=1413335361/*!*/;

    12    SET@@session.pseudo_thread_id=1/*!*/;

    13    SET@@session.foreign_key_checks=1, @@session.sql_auto_is_null=0,@@session.unique_checks=1, @@session.autocommit=1/*!*/;

    14    SET@@session.sql_mode=0/*!*/;

    15    SET@@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;

    16    /*!\Cutf8 *//*!*/;

    17    SET@@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;

    18    SET@@session.lc_time_names=0/*!*/;

    19    SET@@session.collation_database=DEFAULT/*!*/;

    20    createtable employee ( id int auto_increment,name char(64) not null,emailchar(64),password char(64),primary key (id) )

    21    /*!*/;

    22    #at 428

    23    #141015  9:12:27 server id 1  end_log_pos 496      Query     thread_id=1    exec_time=0   error_code=0

    24    SETTIMESTAMP=1413335547/*!*/;

    25    BEGIN

    26    /*!*/;

 

    1~7行相對應的部分,它們修復序言中設置的值,然後回滾所有活動事務。

    每當數據庫更改時,第10行的use語句會被打印,當一個use語句出現時,他就是一個新事件的第一行。

    緊接在use語句下面一行是SET TIMESTAMP 這個語句提供自紀元時間開始以秒計算的事件開始執行時的時間戳。

    12~19行包含常規設置,類似於第10行的use,只有第一個事件和當它們的值被改變時,它們纔會被打印。

註釋詳解

# at 245

#141015  9:09:21 server id 1  end_log_pos 428    Query     thread_id=1

       exec_time=0   error_code=0

註釋的各部分意義如下:

at 245

事件開始的字節位置,也就是該事件的第一個字節;

141015  9:09:21

事件被寫入二進制日誌的時間;

Server id 1

產生該事件的服務器的server id

end_log_pos 428

緊接着該事件之後,下一個事件開始的字節位置;

Query

事件類型,例如User_varIntvarXid

thread_id=1

執行該事件的線程ID

exec_time=0

以秒爲單位的查詢執行時間;

error_code=0

從語句執行結果得到的錯誤碼;


二進制日誌配置選項

expire-log-days=days

binlog需要保留的天數。當二進制日誌已經輪換或服務器重啓時,比指定數值老的文件將從文件系統中刪除。這個選項默認是0,意味着binlog文件永遠不會被刪除。

 

log-bin [ =basename ]

通過在my.cnf中添加log-bin選項來開啓二進制日誌,這個選項還給出了binlog文件的基本名稱,也就是在圓點之前的部分文件名。如果該選項沒有指定basename,則基本名默認爲host-bin,強烈建議給log-bin選項賦值。否則當hostname改變時,binlog文件將改名(除非pid-file被給定一個確切值)。

 

log-bin-index [ =filename ]

給出索引文件的名稱,與log-bin選項情況類似,hostname將被用來組成索引文件名,意味着如果hostname改變,複製將中斷,出於這個原因建議給這個選項賦值。

 

binlog-cache-size=bytes

事務緩存,當事務緩存的大小超過該值時,剩餘的數據將進入磁盤。這有可能造成性能問題,因此如果你使用許多大型事務,增大該選項可以提高性能。

注意,只分配非常大的緩衝區並不是好主意,因爲這意味着服務器的其他部分得到更少的內存,這可能導致性能下降。

 

max-binlog-cache-size=bytes

使用這個選項來限制在二進制日誌中的每個事務的大小。由於大型事務有可能阻塞二進制日誌很長時間,他們將導致其他線程爲二進制日誌護航二造成重大性能問題。如果事務的大小超過bytes,該語句將出錯而被終止。

 

max-binlog-size=bytes

指定每個binlog文件的大小,如事務或語句超過了max-binlog-size,二進制日誌將被輪換,該事務全部內容將被寫入新的文件,因爲事務永遠不會被分割到不同的binlog文件。

 

sync-binlog=period (時段,週期)

指定多長時間通過fdatasync寫二進制日誌到磁盤一次,如果給定的數值爲1,每次事務提交時調用fdatasync,而如果給定值爲10,則每10個事務提交將調用一次fdatasync。數值爲0表示永遠不會調用,而且服務器相信操作系統會寫二進制日誌到磁盤,作爲正常文件處理的一部分。

 

read-only

防止任何客戶端進程(除了Slave進程和有SUPER權限的用戶)更新服務器上的任何數據。


本篇內容純手打,是筆者看書學到的知識,從中摘取了一些比較關鍵的內容和筆者的實驗過程記錄了下來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章