程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL復制(二) --- 二進制日志怎麼干活的

MySQL復制(二) --- 二進制日志怎麼干活的

編輯:MySQL綜合教程

由之前的文章可以了解到,二進制日志在復制中起到舉足輕重的作用,所以這一篇文章著重了解一下Mysql復制背後核心組件:二進制日志的廬山真面目。

二進制日志的結構

從概念上講,二進制日志是一系列二進制日志事件。它包括一系列的binlog文件和一個binlog索引文件,當前服務器正在寫入的binlog文件稱之為active binlog。其文件名是通過配置文件中的log-bin和log-bin-index來定義的。

每個binlog文件是由若干binlog事件組成,以Format_description事件開始,以Rotate事件作為文件尾。

Format_description事件包含寫binlog文件的服務器信息,以及關於文件狀態的關鍵信息。如果服務器關閉或者重新啟動,會創建一個新的binlog文件,同時寫入新的Format_description事件,這個事件是必須的,因為服務器關閉和重啟都會產生更新。服務器寫完binlog文件後,在文件結尾添加一個Rotate事件,該事件包含下一個binlog文件的文件名及其開始讀取的位置。除了Format_description和Rotate事件之外,binlog文件的其他事件都被分成 group進行管理。在事務存儲引擎中,每個組大致對應一個事務,對於非事務存儲引擎,每個語句本身就是一個組。通常情況下,每個組要麼全部執行,要麼去不執行。如果由於某種原因Slave在組執行的過程中停機,那麼將從該組的起點而不是剛剛執行的語句開始復制。

binlog事件的結構

二進制日志版本4(binlog format 4)是在MySQL 5.0中引入,是專門為擴展而設計的。這裡主要討論二進制日志版本4。(MySQL 3.23 4.0 4.1版本都是使用二進制日志版本3)

每個binlog事件由三個部分組成:

  • 通用頭(common header):大小固定。事件的基本信息,其中重要的字段是事件類型和事件大小。
  • 提交頭(post header):大小固定。提交頭與特定的事件類型相關
  • 事件體(Event body):大小可變。事件體存儲事件的主要數據,因事件類型不同而異。

具體看一下Format_description事件:

  • binlog文件格式版本
  • 服務器版本字符串:一般包括三部分,即版本號、連字符和其他構建項。例如:5.1.42-debug-log
  • 通用頭的長度:存儲了通用頭的長度。這裡是指Format_description事件,所以不同binlog文件該字段的值不同。除了Format_description和Rotate事件外,其他事件的通用頭長度都是可變的。Format_description事件的通用頭長度是不變的,是因為任何版本的服務器都需要讀取這個事件。Rotate事件的通用頭長度也是不變的,是因為Slave連接Master時首先要用到該事件。
  • 提交頭的長度:binlog文件中所有事件的提交頭長度是不變的,該字段存儲了各個事件的提交頭長度構成的數組。由於不同服務器間的事件數目不同,所以這個字段前面還存儲了服務器的事件數目。

通過事件來記錄數據庫變更

首先,由於二進制日志是公共資源,所有線程都向它寫入語句,為了避免兩個線程同時更新二進制日志,在寫之前需要獲得一個互斥鎖Lock_log,寫完之後再釋放。

所有涉及到數據庫更新的語句都會以Query事件的形式寫入二進制日志中,除了實際執行的語句外,Query事件還包含執行語句必需的上下文附加信息。下面給出了如何記錄這些上下文信息

  • 當前數據庫:在Query事件添加一個特殊字段記錄當前數據庫。
  • 用戶自定義變量的值:User_var事件記錄單個用戶自定義的變量的變量名及其值。
  • RAND函數的種子:Rand事件記錄Rand函數所用的隨機數種子。
  • 當前時間:NOW,CURDATE,CURTIME,UNIX_TIMESTAMP和SYSDATE這五個函數會用到當前時間,針對這個事件會存儲一個時間戳,表示事件何時開始執行。
  • AUTO_INCREMENT字段的插入值:Intvar事件記錄在語句開始前,表內部的自動增量計數器的值。
  • 調用LAST_INSERTED_ID的返回值:Intvar事件記錄這個函數在語句的返回值。
  • 線程ID:主要是涉及到臨時表的處理。線程ID也是作為一個獨立的字段存儲在Query事件中。

* 對於SYSDATE函數,它返回的是函數執行時的時間,這一點不同於NOW函數,NOW返回的是語句執行的時間。所以SYSDATE對於復制來說是不安全的,盡量少用。

LOAD DATA INFILE語句

LOAD DATA INFILE比較特殊,它的上下文是文件系統的文件。要正確地傳遞和執行LOAD DATA INFILE語句,需要引入新的事件類型:

  • Begin_load_query:這個事件開始傳輸文件中的數據
  • Append_block:如果這個文件超過了連接的數據包大小所允許的最大值,那麼跟隨在Begin_load_query事件後面的一個或多個Append_block事件的系列包含著這個文件的剩余部分
  • Execute_load_query:Query事件的特殊變種,它包含了在Master上執行的LOAD DATA INFILE語句

對Master上執行的每個LOAD DATA INFILE語句而言,被讀取的文件被映射到一個支持內部文件的緩沖區,並在接下來的處理流程中使用。此外,一個唯一的文件ID被分配給該執行語句,並用於指向該語句讀取的文件。

當語句在執行的時,該文件的內容被寫入二進制日志,作為以Begin_load_query事件開頭的事件序列,Begin_load_query事件表示新文件的開始,且這個事件序列後面緊跟著零個或多個Append_block事件。每個寫入二進制的事件都不會超過包大小所允許的最大值,這個最大值由max-allowed_packet選項指定。

當整個文件讀取到表中後,通過寫Execute_load_query事件到二進制日志來終止語句的執行。這個事件包含了執行語句和分配給該執行語句的文件ID。請注意,這並非是用戶寫的原始語句,而是重新創建的。

* Mysql 5.0.3之前的版本使用的事件名有點不一樣,依次為Load_log_event,Execute_log_event,Create_file_log_event

二進制日志過濾器

my.cnf中有兩個選項可用於過濾日志:binlog-do-db和binlog-ignore-db。這兩個選項可以使用多次。

MySQL過濾事件的方式對於不熟悉的人來說可能有點奇怪。Mysql過濾是在語句級完成的,binlog-*-db使用當前數據庫來決定是否應該過濾該語句,而不是由語句所影響的表所在的數據庫決定的。對於下面的例子,使用binlog-ignore-db=bad篩選bad數據庫,下例中一個都不會寫入日志。

	USE bad; INSERT INTO t1 VALUES (1),(2);
USE bad; INSERT INTO good.t2 VALUES (1),(2);
USE bad; UPDATE good.t1, ugly.t2 SET a = b;

至於為什麼不是以語句所影響的表所在的數據庫來決定,可以嘗試分析一下。如果以這種邏輯,使用binlog-ignore-db=ugly篩選時,第三條語句到底要不要寫入日志呢?

為了避免在執行可能被過濾的語句時發生錯誤,請不要編寫那種表名,函數名或存儲過程名前面加數據庫名的語句,而是通過使用use來改變當前數據庫。

還有一個需要說明的是,只要設置了binlog-do-db,過濾器會無視binlog-ignore-db的設置。

當然對於MySQL復制來說,本身不建議使用過濾器,因為日志是不完整的。

 

二進制日志和安全

一般來說,一個有REPLICATION SLAVE權限的用戶擁有讀取Master上發生的所有事件的權限,因此為了安全應該保護該賬戶不被損害。具體預防的措施有:

  • 盡可能使從防火牆外無法登錄該賬戶
  • 記錄所有試圖登錄到該賬戶的日志,並將日志放置在一個單獨的安全服務器上
  • 加密Master和Slave間所用的連接,例如MySQL的built-in SLL
  • 敏感信息不要放入日志文件中,比如說密碼
	# 第二種做法不會把明文密碼寫入到日志中,更安全些

UPDATE employee SET pass = PASSWORD('foobar')

SET @pass = PASSWORD('foobar');
UPDATE employee SET pass = @pass
 

觸發器

為了在服務器上重放二進制日志,毫無問題的處理各種表的權限,有必要用SUPER權限的用戶執行所有語句。但觸發器沒有被定義使用SUPER權限,所以重要的是以正確的用戶作為觸發器的定義者去重新創建觸發器。CREATE TRIGGER提供了一個DEFINER子句,如果沒有給語句指定DEFINER,該語句添加DEFINER子句後被寫到二進制日志中,且使用當前用戶作為其定義者。

	master>SHOW BINLOG EVENTS FROM 92236 LIMIT 1\G
******************** 1. row ********************
     Log_name: master-bin.000038
          Pos: 92236
   Event_type: Query
    Server_id: 1
  End_log_pos: 92491
         Info: use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER ...

調用觸發器的語句被記錄到二進制日志,但它沒有連接到特定的觸發器。相反,當Slave執行該語句時,它會自動執行受該語句影響的表相關聯的所有觸發器,這意味著可以在Master和Slave上有不同的觸發器。

存儲過程

存儲過程的定義語句的處理和觸發器是類似的,CREATE PROCETURE語句也有可選的子語句DEFINER,寫入二進制日志的時候,會強制加上該子句的。調用過程和觸發器不一樣。

	

       # 定義存儲過程

delimiter $$

CREATE PROCEDURE employee_add(p_name CHAR(64), p_email CHAR(64), p_password CHAR(64))

    MODIFIES SQL DATA

BEGIN

    DECLARE pass CHAR(64);

    set pass = PASSWORD(p_pass)

    INSERT INTO employee(name, email, password) VALUES (p_name, p_email, pass);

END $$

delimiter ;

 

# 調用存儲過程

master> CALL employee_add('chunk', '[email protected]', 'abrakadabra');

master> SHOW BINLOG EVENTS FROM 104033\G

******************** 1. row ********************

     Log_name: master-bin.000038

          Pos: 104033

   Event_type: Intvar

    Server_id: 1

  End_log_pos: 104061

         Info: INSERT_ID=1

******************** 2. row ********************

     Log_name: master-bin.000038

          Pos: 104061

   Event_type: Query

    Server_id: 1

  End_log_pos: 104416

         Info: use `test`; INSERT INTO employee(name, email, password) VALUES(

         NAME_CONST('p_name',_latin1'chuck' COLLATE 'latin1_swedish_ci'),

         NAME_CONST('p_email',_latin1'[email protected]' COLLATE 'latin1_swedish_ci'),

         NAME_CONST('pass',_latin1'*FEB778934FDSFQOPL7...' COLLATE 'latin1_swedish_ci'))

有四點需要注意:

 

CALL語句沒有被寫入二進制日志。取而代之的是,執行語句作為調用的結果被寫入二進制日志。

該語句改寫為不包含任何對存儲過程的參數的引用。取而代之的是,使用NAME_CONST函數為每個參數創建一個單值的結果集

局部聲明的變量pass也被換成了NAME_CONST表達式

調用語句寫入二進制日志之前,上下文信息已經寫入日志,這裡指Intvar事件

存儲函數

存儲過程的定義語句的處理和觸發器是類似的,CREATE FUNCTION語句也有可選的子語句DEFINER,寫入二進制日志的時候,會強制加上該子句的。調用的時候,存儲函數以與觸發器相同的方式被復制。有一點需要注意的就是,SELECT語句不會被寫入二進制日志,但是一個含有存儲函數的SELECT語句是個例外。

對於存儲函數還有一個需要提到的是權限問題。CREATE ROUTINE權限是定義一個存儲過程或存儲函數所必需的。嚴格說創建一個存儲程序不需要其他權限,但它通常根據定義者的權限執行。在Slave上的復制線程在不進行權限檢查的情況下執行,這留下了嚴重的安全漏洞。MySQL 5.0之前的版本沒有存儲程序,這樣不會有問題,因為在Master上違規的語句不會寫到二進制日志中。由於存儲過程被展開了,只有在Master上成功執行的語句才會寫進二進制日志,所以也不會有問題。而存儲函數有點不同,它並沒有被展開,也就是說有可能在Master和Slave上執行不同的程序分支,帶來潛在安全漏洞。在存儲函數定義時使用SQL SECURITY DEFINER而不是SQL SECURITY INVOKER可以防止這一點。因為這一點的考慮,MySQL默認要求SUPER權限來定義存儲函數。

Events

定義跟其他存儲程序一樣,也會有DEFINER子句。由於事件由事件調度器調用,因此它們總是以定義者執行從而不會存在存儲函數的安全漏洞。當事件被執行時,該語句被直接寫入二進制日志。由於事件是在Master上執行的,他們在Slave上是自動禁止的。但有時候如果需要升級Slave,就需要允許在Slave上執行這些事件。

	UPDATE mysql.events SET status = ENABLED WHERE status = SLAVESIDE_DISABLED;

特殊結構

盡管基於語句的復制通常是簡單的,但一些特殊結構必須小心處理,才能很好的來保證Slave執行語句時的上下文跟Master上執行時是一樣的。

 

LOAD_FILE函數

LOAD_FILE函數讓你可以獲取一個文件,由於在復制過程中,它不會被傳輸,所以需要改寫。

	INSERT INTO document(author, body) VALUES ('Fox', LOAD_FILR('index.html'));

# 可以用LOAD DATA FILE改寫
LOAD DATA INFILE 'index.html' INTO TABLE document FIELDS TERMINATED BY '@*@' LINES TERMINATED BY '&%&' (author, body) SET author = 'FOX';

# 還可以用用戶定義變量改寫
SET @document = LOAD_FILE('index.html');
INSERT INTO document(author, body) VALUES ('Fox', @document);

 

非事務性的變化和錯誤處理

如果有一個employee表是支持事務的InnoDB存儲引擎(主鍵是mail),而跟蹤employee修改的log表是不支持事務的MyISAM存儲引擎。在其上定義兩個觸發器,一個在INSERT之前觸發tr_insert_before,插入一條記錄到log表,插入紀錄的狀態為FAIL;一個在INSERT之後觸發tr_insert_after,更改剛才插入紀錄的狀態為OK。連續插入兩條完全相同記錄時,tr_insert_before被觸發,tr_insert_after則不會被觸發。雖然employee失敗回滾了,但是log裡面插入的數據卻沒辦法回滾,這是個問題。執行後二進制日志文件內容如下。

	master> SET @pass = PASSWORD('xyz');
master> INSERT INTO employee (name, mail, password) VALUES ('hu', '[email protected]', @pass);
master> INSERT INTO employee (name, mail, password) VALUES ('hu', '[email protected]', @pass);
master> SHOW BINLOG EVENTS IN 'local-bin.000023'
******************** 1. row ********************
     Log_name: master-bin.000023
          Pos: 1252
   Event_type: Query
    Server_id: 1
  End_log_pos: 1320
         Info: use 'test'; BEGIN
******************** 2. row ********************
     Log_name: master-bin.000023
          Pos: 1320
   Event_type: Intvar
    Server_id: 1
  End_log_pos: 1348
         Info: LAST_INSERT_ID=1
******************** 3. row ********************
     Log_name: master-bin.000023
          Pos: 1348
   Event_type: User var
    Server_id: 1
  End_log_pos: 1426
         Info: @'pass'=_utf 0x432423jklfslagklr... COLLATE utf8_general_ci
******************** 4. row ********************
     Log_name: master-bin.000023
          Pos: 1426
   Event_type: Query
    Server_id: 1
  End_log_pos: 1567
         Info: use 'test'; INSERT INTO employee ...
******************** 5. row ********************
     Log_name: master-bin.000023
          Pos: 1567
   Event_type: Xid
    Server_id: 1
  End_log_pos: 1594
         Info: COMMIT /* xid=60 */
******************** 6. row ********************
     Log_name: master-bin.000023
          Pos: 1594
   Event_type: Query
    Server_id: 1
  End_log_pos: 1662
         Info: use 'test'; BEGIN
******************** 7. row ********************
     Log_name: master-bin.000023
          Pos: 1662
   Event_type: Intvar
    Server_id: 1
  End_log_pos: 1690
         Info: LAST_INSERT_ID=1
******************** 8. row ********************
     Log_name: master-bin.000023
          Pos: 1690
   Event_type: User var
    Server_id: 1
  End_log_pos: 1768
         Info: @'pass'=_utf 0x432423jklfslagklr... COLLATE utf8_general_ci
******************** 9. row ********************
     Log_name: master-bin.000023
          Pos: 1768
   Event_type: Query
    Server_id: 1
  End_log_pos: 1909
         Info: use 'test'; INSERT INTO employee ...
******************** 10. row ********************
     Log_name: master-bin.000023
          Pos: 1909
   Event_type: Query
    Server_id: 1
  End_log_pos: 1980
         Info: use 'test'; ROLLBACK

 

事務

由上面的二進制日志內容可以看到,執行事務的時候需要額外的處理。對於事務來說,為了使得每個事務的所有語句在一起,不是按照事務的開始順序而是提交順序記入二進制日志。為了確保每個事務都作為一個單元被寫入二進制日志,服務器需要將在不同線程中執行的語句分開,保存在一個事務緩存中,在事務提交的時候緩存被清空,同時事務緩存的內容被復制到二進制日志中。

那如何記錄非事務性的語句呢?有這麼三條規則可以使用:

  1. 如果語句被標記成事務的,它將被寫入事務緩存
  2. 如果語句沒有被標記成事務性的,而且事務緩存中沒有語句,該語句將被直接寫入二進制日志
  3. 如果語句沒有被標記成事務性的,但是事務緩存中已有語句,該語句被寫入事務緩存
如果一個事務裡面涉及到非事務性語句時候,確保影響非事務性表的語句在事務中首先被寫入,此時根據規則2會直接寫入二進制日志。如果在事務的後面語句中,需要從這些語句中取到任何值,可以分配他們到臨時表或變量。  

使用XA進行分布式事務處理

XA包含一個事務管理器,協調一系列的資源管理器,以便於它們將一個全局的事務當作一個原子單元進行提交。每個事務都被分配一個唯一的XID,這個XID被事務管理器和資源管理器使用。當在MySQL服務器內部使用時,事務管理器通常是二進制日志而資源管理器是存儲引擎。 提交一個XA事務的過程:
  1. 第一階段,每個存儲引擎被要求為提交做准備。在准備時,存儲引擎將它需要正確提交的一切信息寫入到安全的存儲器,然後返回一個OK消息。如果有一個存儲引擎的回答是否定的,則意味著它不能提交這個事務,提交被終止,而且所有的引擎都被通知回滾事務。
  2. 在所有的存儲引擎都返回OK的時候,在第二階段開始之前,事務緩存被寫入二進制日志。普通事務以帶有COMMIT的普通查詢事件結束,與此同時,XA事務則以一個包含XID的Xid事件結束。
在第二階段,在第一階段中准備好的所有存儲引擎都被要求提交事務。當提交時,每個存儲引擎都將報告它已經在持久存儲器中提交了事務。理解提交不能失敗是非常重要:一旦階段一已經通過,存儲引擎就要保證事務能被提交,從而不能在階段2報告失敗。即使硬件錯誤導致系統崩潰,但是由於存儲引擎已經在持久存儲引擎中存儲了這些信息,在服務器重啟後,它們將能夠正確恢復。恢復流程大概是:啟動時,服務器將打開最後一個二進制日志並檢查Format description事件。如果binlog-in-use標志被設置,那麼表示服務器已經崩潰而且需要執行XA恢復。服務器通過查看活動的二進制日志來讀取Xid事件,並從二進制日志中查找所有事務的XID。每個存儲引擎啟動後馬上被要求提交列表中的事務。對於列表中每個XID,存儲引擎將確定哪個XID對應的事務是已經准備好但沒有提交的,如果是就提交這個事務。如果存儲引擎准備的事務XID不在此列表中,那麼這個XID顯然在服務器崩潰前沒有被寫入二進制日志,因此這個事務必須被回滾。  

二進制日志管理

到目前為止,所提到的事件都是Master上的數據的改動。有一些事件雖然不是代表在Master上修改數據,但它們卻會影響復制。比如在服務器停止的期間修改了數據文件之類,為了應對這些問題,也需要額外類型的事件。

二進制日志和系統崩潰安全

在數據庫崩潰的時候,保持數據庫和二進制日志相互一致性非常重要。換句話說,如果沒有寫入二進制日志,那麼就應該沒有更改被提交到存儲引擎,反之亦然。

但對於非事務性引擎則有問題。例如,不可能保證二進制日志和MyISAM表之間的一致性,因為MyISAM是非事務性的,且MyISAM在試圖記錄語句之前就完成了修改。對於事務性存儲引擎則不一樣。正如前面所講,事件被寫入二進制日志是在釋放所有表鎖之前,所有改變傳輸到各個存儲引擎之後的。如果在存儲引擎釋放鎖之前系統宕機了,服務器在允許事務提交之前一定要確認寫進二進制日志的改變已經寫進實際表中,而這是需要和標准文件系統同步進行協調。

回憶一下XA,為了能安全應對宕機,當第一階段完成的時候,所有的數據都應該已經寫到了磁盤。這就意味著每次一個事務完成,系統頁緩存(page cache)就必須寫到磁盤,這種想法的代價很高,而且很多應用並不必須這樣。可以通過sync-binlog選項來控制數據寫磁盤的頻率,默認為0,也就是不寫磁盤的調度完全交給操作系統;設置n,表示每n次事務提交就寫一次磁盤。

 

binlog文件輪換(binlog file rotate) 

MySQL隔一段時間就會啟用一個新文件來保存二進制日志事件。把文件切換稱之為binlog file rotate。

主要有四種操作會導致文件輪換:

  1. 服務器停止:每次服務啟動都會啟用一個新的二進制日志文件。
  2. binlog文件大小達到最大值:這個值可以通過binlog-cache-size參數控制。
  3. 顯式刷新:FLUSH LOGS
  4. 服務器發生事故:有些事故需要特殊的人工干預,這都會在復制流程上形成一個"缺口"
每個二進制日志都是以Format description事件開始的,該事件描述服務器的信息以及文件的狀態和內容的信息。其中有幾個需要關注:
  • binlog-in-use標志位:服務器在寫二進制日志時有可能發生宕機,因此需要知道一個文件是否被正確的關閉。而且,如果一個文件本身損壞了,用它進行恢復會產生更多的問題。binlog-in-use就是用於標識一個文件的完整性,它在文件創建的時候被設置,在Rotate事件被寫入文件後被清除。
  • 二進制日志文件格式版本號:
  • 服務器版本:
為了使得即使是在宕機的情況下,也能安全的切換日志文件,服務器采用了預寫策略,在一個臨時文件裡寫明其意圖,該臨時文件被稱為purge index file(之所以這麼叫是因為在清除二進制日志時它也被使用了),文件名是基於二進制日志索引文件名。當創建了新的二進制日志文件,並更新了索引文件之後,服務器會刪除該臨時文件。  

Incidents

 所謂incident事件是指那些在服務器上沒有產生數據改變但卻必須要寫進二進制日志的事件,因為它們有可能影響到復制。大多數這種事件並不需要DBA干預,比如數據庫的重啟等。

  •  stop:這是一種表示服務器正常關機的事件。如果服務器宕機,就不會有stop事件。這個事件會在舊的二進制日志文件裡,因為重啟會啟用新文件。該事件僅僅包含一個通用頭。當二進制日志在Slave上重放的時候,所有Stop事件都會被忽略。那這種事件有什麼用呢,因為重啟復制前可能手動恢復一個備份或者修改了文件,這時候DBA在重放該日志文件的時候,可以找到該事件從而知道在哪裡開始或者停止重放。
  • Incident:該事件類型是在MySQL 5.1版本引入的。和Stop事件相比,該事件包含一個標志符來指定發生了哪種類型事故。它一般用來表示服務器被強制執行某個不被記入二進制日志的變更。比如,數據庫重新加載,某個非事務性事件太大而無法寫入二進制日志。MySQL Cluster在其中一個節點重新加載數據庫而因此不同步時也會產生該事件。當二進制日志在Slave上重放的時候,碰到Incident事件的時候將會停止復制。

刪除二進制文件

 有幾種方式可以刪除二進制文件:

	1:設置my.cnf的expire-logs-days參數
2:PURGE BINARY LOGS BEFORE datetime;
3:PURGE BINARY LOGS TO 'filename';

刪除二進制文件的機制:
開始刪除文件之前,服務器會把要刪除的文件列表寫到一個臨時文件(purge index file),然後才開始刪除文件,最後刪除該臨時文件。這樣即使在刪除日志文件過程中系統宕機也能在服務器再啟動時,繼續刪除未刪除的文件。在前面講到,purge index file也用於文件rotate的時候。

mysqlbinlog是一個可以查看binlog日志文件和relay日志文件內容的小程序。用mysqlbinlog工具來查看二進制日志內容的輸出是可以直接在服務器上執行的。該命令是分析日志的一個利器,可以查看所有日志的語句內容和事件內容,因此用來查錯。該命令的具體使用方法參照官方文檔。注意可以用使用--hexdump選項來查看二進制日志,不過需要了解一下日志的數據格式。比如二進制日志的整數字段是以little-Endian順序打印出來的,所以你必須從右往左讀。32位的block 03 01 00 00表示16進制的103。

 

 

 

---待續

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved