1. 程式人生 > 實用技巧 >MySQL二進位制日誌

MySQL二進位制日誌

MySQL二進位制日誌—binlog

MySQL二進位制日誌—binlog
一、什麼是二進位制日誌
1.概念
2.具體分析
二、二進位制日誌的作用
1.基於時間點的恢復原理
三、二進位制日誌的模式以及相關引數
binlog的模式:statement、row、mixed
引數1:log_bin
引數2:sql_log_bin
引數3:binlog_format
引數4:max_binlog_size
引數5:sync_binlog
四、具體測試
五、關於mysqlbinlog命令toc

一、什麼是二進位制日誌

1.概念

  二進位制日誌被稱為binlog,它會記錄所有的修改資料庫的語句或者有可能改變資料庫的語句,但是像select,show等不會對資料庫進行寫操作的語句不會被記錄。

2.具體分析

  二進位制日誌,內容是二進位制的也就是說使用cat等命令是無法直接檢視的,在二進位制日誌中有著“事件”,“位置”的概念的。
事件:events。在binlog中每一條記錄都可以當作是一個“事件”,因為二進位制日誌記錄的是對資料庫的修改,也就是每有一次修改就有一個“事件”被記錄在了二進位制日誌中。
位置:position。因為是二進位制的檔案,所以其內容可以當作是一個很長的序列。二進位制日誌從為空到記錄事件,整個事件長度為10個位元組,那麼這個事件開始的位置就是1,結束的位置就是10。下一個事件開始的位置起始點就是11。這個在主從結構搭建中從定位主的日誌起到關鍵作用。

二、二進位制日誌的作用

  使用二進位制日誌的主要目的是最大可能的恢復資料庫。因為二進位制日誌包含備份後進行的所有更新,不記錄沒有修改任何資料的語句。同時二進位制日誌也被應用與主從複製結構。

1.基於時間點的恢復原理

  現在假設一個場景,每天凌晨2點開始備份資料庫並且備份成功,在當天9點資料庫崩潰,那麼該如何恢復?我們可以利用2點的備份進行恢復,但是隻能將資料庫恢復到凌晨2點,那麼2點到9點這部分資料就會丟失。這個時候就需要使用二進位制日誌。首先將資料庫恢復到凌晨2點的狀態,利用二進位制日誌將這期間的操作重做一次,那麼就保證了資料的安全性不會丟失,這就是二進位制日誌的恢復作用。

三、二進位制日誌的模式以及相關引數

  根據上面所說的我們已經知道了binlog日誌記錄的是對資料庫的所有操作。如果現在我們用自己的賬戶在對資料庫進行操作其中使用了user()函式並且做了修改,binlog順利記錄但是隻記錄了user()這個語句並沒有記錄是哪個使用者操作的,需要恢復時用的是其他使用者恢復的,那麼和user()相關的資料恢復完是和原來的資料不一致的,這種資料恢復就是失敗的。所以為了確保資料恢復的準確性除了相應的SQL還需要記錄對應的SQL到底修改了資料庫中的哪些行以及如何修改,這樣才能保證我們在進行恢復的時候資料的準確性。但是相應的這也帶來了一個問題,如果這個更新語句是一個update並且是針對一個列做出的修改,假設被修改的表有10000行資料,那麼我的binlog就需要把涉及修改的10000行資料都記錄下來,這對資源是極大的佔用,這種情況其實我只要記錄一下這個SQL就可以沒必要去記錄所有涉及改動的資料。所以綜合來看,這兩種binlog的記錄方式還是各有千秋都有自己的優勢和劣勢。對DBA而言,二進位制日誌的記錄模式是完全可控的,只需要修改binlog的記錄模式就可以實現。

binlog的模式:statement、row、mixed

  • statement:只記錄對資料庫做出修改的語句,例如上例所說的update語句,這時binlog會把更新的語句完整的記錄下來。這種模式的優點就是需要記錄的日誌量很小,相應的對IO的壓力也會小效能上也是最好的。缺點也是上面所說的,使用一些特定的函式可能會導致恢復出現問題。
  • row:記錄對資料庫做出修改的語句所影響到的資料行以及這些行的修改,還是上面update語句,除了記錄語句本身,在row模式下還會把涉及修改的資料行資料和怎樣被修改全部記錄到binlog中。這種模式的優點就是可以完全的還原或者複製日誌被記錄時的操作,缺點是記錄日誌量較大,IO壓力大,效能消耗較大。
  • mixed:混合使用上述兩種模式,一般的語句使用statment方式進行儲存,如果遇到一些特殊的函式,則使用row模式進行記錄,這種記錄方式被稱之為mixed,看上去這種方式似乎比較完美,但是在生產環境中為了保險起見,一般會使用row模式。

修改binlog模式:
可以使用binlog_format變數設定二進位制日誌的記錄方式,也可以在my.cnf配置檔案中加入如下配置使其永久生效

[root@mysql8 mysql_3306]# vim my_3306.cnf
...
binlog_format = row
....

引數1:log_bin

  這個變數控制著資料庫是否啟動了二進位制日誌,並且這個變數只讀。只讀的意義在於這個變數無法線上通過set進行設定,只能通過修改引數檔案來進行開啟。需要注意的是這個變數不存在ON和OFF的值,只要它在配置檔案中生效就說明已經開啟了二進位制日誌,而它的值會變成資料檔案目錄下二進位制日誌檔名字的字首。想要關閉二進位制日誌要麼把這個變數在配置檔案註釋要麼直接刪除。開啟後我們在配置檔案中通過這個變數的值來設定日誌檔案的字首而後綴會由資料庫自動進行編號當這個日誌檔案慢了或者被切換這個值會自動加1。 需要重啟資料庫才會生效

引數2:sql_log_bin

  首先這是一個會話級別的變數,所以配置檔案中不能有這個。想要修改只能在線通過set修改並且不能使用set global,只在當前會話生效。這個變數主要是控制當前會話中的對資料庫起到修改作用的SQL是否會被記錄在binlog中。假設我的資料庫已經開啟了binlog,我連線上我的資料庫並且在我的這個會話中把sql_log_bin這個變數設定為了OFF,那麼我在這個會話中做的所有對資料庫有修改的語句都不會被記錄在binlog中。在主從同步的場景因為沒有被記錄在binlog所以這些操作也不會被同步到從節點上。

引數3:binlog_format

  這個變數在上文已經介紹的差不多了,決定了資料庫binlog的模式,推薦生產環境使用row模式保證資料的安全性。

引數4:max_binlog_size

  設定單個二進位制日誌檔案的大小,單位是位元組,當日志文件的大小超過這個限制日誌檔案自動滾動並且字尾自動加1。

引數5:sync_binlog

  這個變數用來控制二進位制日誌同步。二進位制日誌是在記憶體中被記錄的,這點和Oracle中的redo buffer cache一樣存在快取區,而二進位制日誌在記憶體中的binlog_cache中存放。如果將這個變數設定為1,那麼每當一個事務被提交那麼存放在記憶體中的binlog資訊就會落盤到資料檔案上。如果為0,那麼這個落盤基於檔案系統的快取機制來確定。總得來說為0時效能最好但是安全性最差,一旦斷電記憶體中的資料全部丟失。值為1效能最差但是安全性也是最好的。除此之外,這個值可以是其他數字如,2,3,4等意味著幾次事務落一次盤。所以究竟使用幾還需要視情況而定,效能影響也是很大的。

四、具體測試

  • 查詢當前資料庫是否開啟二進位制日誌
mysql> show variables like '%log_bin'; #預設通常是不開啟的
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
| sql_log_bin   | ON    |
+---------------+-------+
2 rows in set (0.00 sec)
  • 手動開啟二進位制日誌
# 1.首先修改配置檔案
[root@mysql8 mysql_3306]# pwd
/data/mysql/mysql_3306
[root@mysql8 mysql_3306]# vim my_3306.cnf 
...
log-bin = /data/mysql/mysql_3306/logs/mysql-bin #我這裡填寫的是mysql-bin作為字首
...
# 2.重啟資料庫
[root@mysql8 mysql_3306]# systemctl start mysqld #我用的MySQL8自己配置的服務,啟動方式可能不同,我在之前的文章中寫過具體配置
[root@mysql8 logs]# pwd
/data/mysql/mysql_3306/logs
[root@mysql8 logs]# ls
error.log  mysql-bin.000001  mysql-bin.000002  mysql-bin.000003  mysql-bin.000004  mysql-bin.index  slow.log
  • 在MySQL中檢視二進位制日誌的檔案列表(兩種方式均可,最後一列為是否加密,這應該是8的新特性)
mysql> show binary logs;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 |       178 | No        |
| mysql-bin.000002 |      2322 | No        |
| mysql-bin.000003 |      1851 | No        |
| mysql-bin.000004 |       195 | No        |
+------------------+-----------+-----------+
4 rows in set (0.00 sec)

mysql> show master logs;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 |       178 | No        |
| mysql-bin.000002 |      2322 | No        |
| mysql-bin.000003 |      1851 | No        |
| mysql-bin.000004 |       195 | No        |
+------------------+-----------+-----------+
4 rows in set (0.00 sec)
  • 檢視當前資料庫binlog的記錄模式
mysql> show variables like '%binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)
  • 接下來對資料庫進行一些操作,看看日誌檔案大小是否會變化
mysql> select * from test;
+------+------+
| id   | name |
+------+------+
|    1 | zs   |
|    2 | ls   |
|    3 | zzl  |
+------+------+
3 rows in set (0.00 sec)

mysql> insert into test values (4,'zzzl');
Query OK, 1 row affected (0.00 sec)

mysql> show binary logs;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 |       178 | No        |
| mysql-bin.000002 |      2322 | No        |
| mysql-bin.000003 |      1851 | No        |
| mysql-bin.000004 |       483 | No        | #和上面相比這個是變大的
+------------------+-----------+-----------+
4 rows in set (0.00 sec)
# 做一次查詢
mysql> select * from test;
+------+------+
| id   | name |
+------+------+
|    1 | zs   |
|    2 | ls   |
|    3 | zzl  |
|    4 | zzzl |
+------+------+
4 rows in set (0.00 sec)

mysql> show binary logs;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 |       178 | No        |
| mysql-bin.000002 |      2322 | No        |
| mysql-bin.000003 |      1851 | No        |
| mysql-bin.000004 |       483 | No        | #說明查詢並不會被二進位制日誌記錄下來
+------------------+-----------+-----------+
4 rows in set (0.00 sec)
  • 檢視二進位制日誌記錄的內容
#接著上面的操作繼續就可以,可以看到483位置結束其上面就是所做的操作。
mysql> show binlog events in 'mysql-bin.000004';
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                               |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| mysql-bin.000004 |   4 | Format_desc    |      3306 |         124 | Server ver: 8.0.15, Binlog ver: 4                                  |
| mysql-bin.000004 | 124 | Previous_gtids |      3306 |         195 | 32415cb9-d5ff-11ea-a561-000c29135205:1-14                          |
| mysql-bin.000004 | 195 | Gtid           |      3306 |         274 | SET @@SESSION.GTID_NEXT= '32415cb9-d5ff-11ea-a561-000c29135205:15' |
| mysql-bin.000004 | 274 | Query          |      3306 |         349 | BEGIN                                                              |
| mysql-bin.000004 | 349 | Table_map      |      3306 |         407 | table_id: 69 (test.test)                                           |
| mysql-bin.000004 | 407 | Write_rows     |      3306 |         452 | table_id: 69 flags: STMT_END_F                                     |
| mysql-bin.000004 | 452 | Xid            |      3306 |         483 | COMMIT /* xid=24 */                                                |
+------------------+-----+----------------+----------- +-------------+--------------------------------------------------------------------+
7 rows in set (0.00 sec)
  • 檢視當前使用哪個二進位制日誌以及所處的位置點以及如何重新整理
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+------------------+----------+--------------+------------------+-------------------------------------------+
| mysql-bin.000004 |      770 |              |                  | 32415cb9-d5ff-11ea-a561-000c29135205:1-16 |
+------------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)
# 重新整理二進位制日誌,會把記憶體中的資訊落盤並切換日誌
mysql> flush logs;
Query OK, 0 rows affected (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+------------------+----------+--------------+------------------+-------------------------------------------+
| mysql-bin.000005 |      195 |              |                  | 32415cb9-d5ff-11ea-a561-000c29135205:1-16 |
+------------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)
  • 開始測試時指定的二進位制日誌存放位置,在其路徑下mysql-bin.index的作用
[root@mysql8 logs]# ls
error.log  mysql-bin.000001  mysql-bin.000002  mysql-bin.000003  mysql-bin.000004  mysql-bin.000005  mysql-bin.index  slow.log
[root@mysql8 logs]# cat mysql-bin.index #就是單純的記錄了有哪些二進位制日誌檔案
/data/mysql/mysql_3306/logs/mysql-bin.000001
/data/mysql/mysql_3306/logs/mysql-bin.000002
/data/mysql/mysql_3306/logs/mysql-bin.000003
/data/mysql/mysql_3306/logs/mysql-bin.000004
/data/mysql/mysql_3306/logs/mysql-bin.000005

五、關於mysqlbinlog命令

  這個命令主要就是為了我們可以在檔案系統層面檢視對應的二進位制日誌

# 檢視全部
[root@mysql8 logs]# mysqlbinlog mysql-bin.000001
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200804 11:04:22 server id 3306  end_log_pos 124 CRC32 0x8d4aeafb       Start: binlog v 4, server v 8.0.15 created 200804 11:04:22 at startup
ROLLBACK/*!*/;
BINLOG '
NtAoXw/qDAAAeAAAAHwAAAAAAAQAOC4wLjE1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA20ChfEwANAAgAAAAABAAEAAAAYAAEGggAAAAICAgCAAAACgoKKioAEjQA
CgH76kqN
'/*!*/;
# at 124
#200804 11:04:22 server id 3306  end_log_pos 155 CRC32 0x13706bcc       Previous-GTIDs
# [empty]
# at 155
#200804 11:04:24 server id 3306  end_log_pos 178 CRC32 0x9604c00a       Stop
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

# 檢視指定位置點
[root@mysql8 logs]# mysqlbinlog --start-position 317 --stop-position 100 mysql-bin.000001 
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

# 檢視指定時間
[root@mysql8 logs]# mysqlbinlog --start-datetime "2020-08-05 15:08:00"  --stop-datetime "2020-08-05 15:13:00" mysql-bin.000004
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200805 11:29:42 server id 3306  end_log_pos 124 CRC32 0xc90b4f28       Start: binlog v 4, server v 8.0.15 created 200805 11:29:42 at startup
ROLLBACK/*!*/;
BINLOG '
picqXw/qDAAAeAAAAHwAAAAAAAQAOC4wLjE1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACmJypfEwANAAgAAAAABAAEAAAAYAAEGggAAAAICAgCAAAACgoKKioAEjQA
CgEoTwvJ
'/*!*/;
# at 770
#200805 15:08:17 server id 3306  end_log_pos 817 CRC32 0x16e772f3       Rotate to mysql-bin.000005  pos: 4
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

參考:http://www.zsythink.net/archives/1286



來自為知筆記(Wiz)