一般情況下,二進制日誌更多的用於數據庫的同步,因爲二進制日誌記錄了數據庫的所有改變,可以使得SLAVE都可以執行同樣的更新,其實二進制日誌可以對數據庫作一個寫入回放,所以也可以用於統計或者即時恢復等其它的目的。
二進制日誌僅僅包含可能改變數據庫的語句,估計都很容易理解這個,但是那些還沒有改變且有可能改變數據庫的語句也會記錄下來,比如drop table if exists或者是帶有WHERE條件的UPDATE和DELETE語句。
一,二進制日誌結構
二進制日誌是一系列二進制日誌事件(又稱爲binlog事件),其實就是很多文件【包括系列日誌文件和一個日誌索引文件】共同組成二進制日誌,這裏每個日誌文件稱爲binlog文件,每個日誌文件由很多個日誌事件組成,每個日誌文件都是以Format_description事件開頭並且以日誌輪換事件Rotate作爲文件結束,如:
mysql> show binlog events in 'master-bin.000003';
+-------------------+-----+-------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+-------------+-----------+-------------+---------------------------------------+
| master-bin.000003 | 4 | Format_desc | 1 | 106 | Server ver: 5.1.34-log, Binlog ver: 4 |
| master-bin.000003 | 106 | Rotate | 1 | 150 | master-bin.000004;pos=4 |
+-------------------+-----+-------------+-----------+-------------+---------------------------------------+
2 rows in set (0.00 sec)
Format_description事件包含寫日誌文件的服務器信息以及日誌文件格式,而Rotate事件包含下一個日誌文件的文件名及其開始讀取的位置。
除了這兩個事件以外,日誌文件中的其他事件都被分成一個組一個組的形式,在事務存儲引擎中,每個組會對應一個事務,而其它有可能是一個語句,總之,日誌文件中的事件要麼是單個語句,要麼是由多條語句組成的事務。
事件類型是有很多種,就是上面的Event_type在實際使用時,會有多個取值,但可以歸納爲每個日誌事件由三個部分組成:
- 通用頭。這部分信息就是所有事件都具備的信息,包含一些基本的信息,比如事件類型以及事件的大小,以上面爲例可以從Pos和End_log_pos計算出這條語句的大小。
- 提交頭。這部分信息和特定的事件類型有關。
- 事件體。這部分信息存儲事件的主要數據,因事件類型不同而不同,例如,事件是Query的時候,存儲查詢語句。如下:
| master-bin.000004 | 180 | Query | 1 | 297 | use `db_info`; insert into i_node(name,value) values("sql",@value)
insert into i_node(name,value) values("sql","copy");
可以得到多了兩條日誌事件| master-bin.000004 | 451 | Intvar | 1 | 479 | INSERT_ID=12 |
| master-bin.000004 | 479 | Query | 1 | 596 | use `db_info`; insert into i_node(name,value) values("sql","copy") |
+-------------------+-----+-------------+-----------+-------------+-----------------------------------------------------------------------------+
其實除此以外,還有其它的一些上下文信息會給當前的執行帶來結果的影響,這些都是MySQL執行時需要知道的隱式信息。如:- 當前數據庫。可以看到我執行insert時,並沒有執行use db_info這條語句,但是也被日誌事件記錄下來。因爲我在最初執行了,後面MYSQL都採用當前的數據庫來執行語句。
- 用戶自定義變量的值。如我執行下面兩條語句之後
mysql> set @value = 'copy-on-write'; Query OK, 0 rows affected (0.00 sec) mysql> insert into i_node(name,value) values("sql",@value); Query OK, 1 row affected (0.00 sec)
可以看到此時的日誌事件如下:
多了一個變量的賦值操作,類型是User var| master-bin.000004 | 596 | Intvar | 1 | 624 | INSERT_ID=13 | | master-bin.000004 | 624 | User var | 1 | 675 | @`value`=_latin1 0x636F70792D6F6E2D7772697465 COLLATE latin1_swedish_ci | | master-bin.000004 | 675 | Query | 1 | 792 | use `db_info`; insert into i_node(name,value) values("sql",@value) |
- RAND()函數的種子。在執行隨機數時,不會記錄其隨機數,會記錄其種子數。
- 當前時間。
- AUTO_INCREMENT字段的插入值,這個是一個上下文,因爲它與前面的行有關。
- LAST_INSERT_ID函數。
- 線程ID,調用CORRENT_ID函數。