千萬不要小看日志
。很多看似奇怪的問題,答案往往就藏在日志里。很多情況下,只有通過查看日志才能發(fā)現(xiàn)問題的原因,真正解決問題。所以,一定要學會查看日志,養(yǎng)成檢查日志的習慣,對提升你的數據庫應用開發(fā)能力至關重要。
MySQL8.0 官網日志地址:“ https://dev.mysql.com/doc/refman/8.0/en/server-logs.html ”
1 MySQL支持的日志
1.1 日志類型
MySQL有不同類型的日志文件,用來存儲不同類型的日志,分為 二進制日志
、 錯誤日志
、 通用查詢日志
和 慢查詢日志
,這也是常用的4種。MySQL 8又新增兩種支持的日志: 中繼日志
和 數據定義語句日志
。使用這些日志文件,可以查看MySQL內部發(fā)生的事情。
這6類日志分別為:
-
慢查詢日志
:記錄所有執(zhí)行時間超過long_query_time的所有查詢,方便我們對查詢進行優(yōu)化。 -
通用查詢日志
:記錄所有連接的起始時間和終止時間,以及連接發(fā)送給數據庫服務器的所有指令,對我們復原操作的實際場景、發(fā)現(xiàn)問題,甚至是對數據庫操作的審計都有很大的幫助。 -
錯誤日志
:記錄MySQL服務的啟動、運行或停止MySQL服務時出現(xiàn)的問題,方便我們了解服務器的狀態(tài),從而對服務器進行維護。 -
二進制日志
:記錄所有更改數據的語句,可以用于主從服務器之間的數據同步,以及服務器遇到故障時數據的無損失恢復。 -
中繼日志
:用于主從服務器架構中,從服務器用來存放主服務器二進制日志內容的一個中間文件。從服務器通過讀取中繼日志的內容,來同步主服務器上的操作。 -
數據定義語句日志
:記錄數據定義語句執(zhí)行的元數據操作。
除二進制日志外,其他日志都是 文本文件
。默認情況下,所有日志創(chuàng)建于 MySQL數據目錄
中。
1.2 日志的弊端
- 日志功能會
降低MySQL數據庫的性能
。 - 日志會
占用大量的磁盤空間
。
2. 慢查詢日志(slow query log)
前面章節(jié)《MySQL基礎(二十七)性能分析工具的使用》已經詳細講述。
3. 通用查詢日志(general query log)
通用查詢日志用來 記錄用戶的所有操作
,包括啟動和關閉MySQL服務、所有用戶的連接開始時間和截止時間、發(fā)給 MySQL 數據庫服務器的所有 SQL 指令等。當我們的數據發(fā)生異常時,查看通用查詢日志,還原操作時的具體場景
,可以幫助我們準確定位問題。
3.1 問題場景
3.2 查看當前狀態(tài)
mysql> SHOW VARIABLES LIKE '%general%';
+------------------+------------------------------+
| Variable_name | Value |
+------------------+------------------------------+
| general_log | OFF | #通用查詢日志處于關閉狀態(tài)
| general_log_file | /var/lib/mysql/DESKTOP-HD37NRE.log | #通用查詢日志文件的名稱是DESKTOP-HD37NRE.log
+------------------+------------------------------+
2 rows in set (0.03 sec)
3.3 啟動日志
方式1:永久性方式
修改my.cnf或者my.ini配置文件來設置。在[mysqld]組下加入log選項,并重啟MySQL服務。格式如下:
[mysqld]
general_log=ON
general_log_file=[path[filename]] #日志文件所在目錄路徑,filename為日志文件名
如果不指定目錄和文件名,通用查詢日志將默認存儲在MySQL數據目錄中的hostname.log文件中,hostname表示主機名。
方式2:臨時性方式
SET GLOBAL general_log=on; # 開啟通用查詢日志
SET GLOBAL general_log_file=’path/filename’; # 設置日志文件保存位置
對應的,關閉操作SQL命令如下:
SET GLOBAL general_log=off; # 關閉通用查詢日志
查看設置后情況:
SHOW VARIABLES LIKE 'general_log%';
3.4 查看日志
通用查詢日志是以 文本文件 的形式存儲在文件系統(tǒng)中的,可以使用 文本編輯器 直接打開日志文件。每臺MySQL服務器的通用查詢日志內容是不同的。
- 在Windows操作系統(tǒng)中,使用文本文件查看器;
- 在Linux系統(tǒng)中,可以使用vi工具或者gedit工具查看;
- 在Mac OSX系統(tǒng)中,可以使用文本文件查看器或者vi等工具查看。
從 SHOW VARIABLES LIKE 'general_log%';
結果中可以看到通用查詢日志的位置。
/usr/sbin/mysqld, Version: 8.0.26 (MySQL Community Server - GPL). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
2022-01-04T07:44:58.052890Z 10 Query SHOW VARIABLES LIKE '%general%'
2022-01-04T07:45:15.666672Z 10 Query SHOW VARIABLES LIKE 'general_log%'
2022-01-04T07:45:28.970765Z 10 Query select * from student
2022-01-04T07:47:38.706804Z 11 Connect root@localhost on using Socket
2022-01-04T07:47:38.707435Z 11 Query select @@version_comment limit 1
2022-01-04T07:48:21.384886Z 12 Connect root@172.16.210.1 on using TCP/IP
2022-01-04T07:48:21.385253Z 12 Query SET NAMES utf8
2022-01-04T07:48:21.385640Z 12 Query USE `test12`
2022-01-04T07:48:21.386179Z 12 Query SHOW FULL TABLES WHERE Table_Type !=
'VIEW'
2022-01-04T07:48:23.901778Z 13 Connect root@172.16.210.1 on using TCP/IP
2022-01-04T07:48:23.902128Z 13 Query SET NAMES utf8
2022-01-04T07:48:23.905179Z 13 Query USE `test`
2022-01-04T07:48:23.905825Z 13 Query SHOW FULL TABLES WHERE Table_Type !=
'VIEW'
2022-01-04T07:48:32.163833Z 14 Connect root@172.16.210.1 on using TCP/IP
2022-01-04T07:48:32.164451Z 14 Query SET NAMES utf8
2022-01-04T07:48:32.164840Z 14 Query USE `test`
2022-01-04T07:48:40.006687Z 14 Query select * from account
在通用查詢日志里面,我們可以清楚地看到,什么時候開啟了新的客戶端登陸數據庫,登錄之后做了什么 SQL 操作,針對的是哪個數據表等信息。
3.5 停止日志
方式1:永久性方式
修改 my.cnf 或者 my.ini 文件,把[mysqld]組下的 general_log 值設置為 OFF 或者把general_log一項注釋掉。修改保存后,再 重啟MySQL服務 ,即可生效。 舉例1:
[mysqld]
general_log=OFF
舉例2:
[mysqld]
#general_log=ON
方式2:臨時性方式
使用SET語句停止MySQL通用查詢日志功能:
SET GLOBAL general_log=off;
查詢通用日志功能:
SHOW VARIABLES LIKE 'general_log%';
3.6 刪除\刷新日志
如果數據的使用非常頻繁,那么通用查詢日志會占用服務器非常大的磁盤空間。數據管理員可以刪除很
長時間之前的查詢日志,以保證MySQL服務器上的硬盤空間。
手動刪除文件
SHOW VARIABLES LIKE 'general_log%';
可以看出,通用查詢日志的目錄默認為MySQL數據目錄。在該目錄下手動刪除通用查詢日志
DESKTOP-HD37NRE.log。
使用如下命令重新生成查詢日志文件,具體命令如下。刷新MySQL數據目錄,發(fā)現(xiàn)創(chuàng)建了新的日志文件。前提一定要開啟通用日志。
mysqladmin -uroot -p flush-logs
4. 錯誤日志(error log)
4.1 啟動日志
在MySQL數據庫中,錯誤日志功能是 默認開啟
的。而且,錯誤日志 無法被禁止
。
默認情況下,錯誤日志存儲在MySQL數據庫的數據文件夾下,名稱默認為 mysqld.log
(Linux系統(tǒng))或hostname.err
(mac系統(tǒng))。如果需要制定文件名,則需要在my.cnf或者my.ini中做如下配置:
[mysqld]
log-error=[path/[filename]] #path為日志文件所在的目錄路徑,filename為日志文件名
修改配置項后,需要重啟MySQL服務以生效。
4.2 查看日志
MySQL錯誤日志是以文本文件形式存儲的,可以使用文本編輯器直接查看。
查詢錯誤日志的存儲路徑:
mysql> SHOW VARIABLES LIKE 'log_err%';
+----------------------------+----------------------------------------+
| Variable_name | Value |
+----------------------------+----------------------------------------+
| log_error | /var/log/mysqld.log |
| log_error_services | log_filter_internal; log_sink_internal |
| log_error_suppression_list | |
| log_error_verbosity | 2 |
+----------------------------+----------------------------------------+
4 rows in set (0.01 sec)
執(zhí)行結果中可以看到錯誤日志文件是mysqld.log,位于MySQL默認的數據目錄下。
4.3 刪除\刷新日志
對于很久以前的錯誤日志,數據庫管理員查看這些錯誤日志的可能性不大,可以將這些錯誤日志刪除,以保證MySQL服務器上的 硬盤空間
。MySQL的錯誤日志是以文本文件的形式存儲在文件系統(tǒng)中的,可以直接刪除
。
[root@atguigu01 log]# mysqladmin -uroot -p flush-logs
Enter password:
mysqladmin: refresh failed; error: 'Could not open file '/var/log/mysqld.log' for
error logging.'
官網提示:
補充操作:
install -omysql -gmysql -m0644 /dev/null /var/log/mysqld.log
5. 二進制日志(bin log
binlog可以說是MySQL中比較 重要
的日志了,在日常開發(fā)及運維過程中,經常會遇到。
binlog即binary log,二進制日志文件,也叫作變更日志(update log)。它記錄了數據庫所有執(zhí)行的DDL
和 DML
等數據庫更新事件的語句,但是不包含沒有修改任何數據的語句(如數據查詢語句select、show等)。
binlog主要應用場景:
- 一是用于
數據恢復
- 二是用于
數據復制
5.1 查看默認情況
查看記錄二進制日志是否開啟:在MySQL8中默認情況下,二進制文件是開啟的。
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/binlog |
| log_bin_index | /var/lib/mysql/binlog.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+----------------------------------+
6 rows in set (0.00 sec)
5.2 日志參數設置
方式1:永久性方式
修改MySQL的 my.cnf
或 my.ini
文件可以設置二進制日志的相關參數:
[mysqld]
#啟用二進制日志
log-bin=atguigu-bin
binlog_expire_logs_seconds=600
max_binlog_size=100M
重新啟動MySQL服務,查詢二進制日志的信息,執(zhí)行結果:
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/atguigu-bin |
| log_bin_index | /var/lib/mysql/atguigu-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+----------------------------------+
6 rows in set (0.00 sec)
設置帶文件夾的bin-log日志存放目錄
如果想改變日志文件的目錄和名稱,可以對my.cnf或my.ini中的log_bin參數修改如下:
[mysqld]
log-bin="/var/lib/mysql/binlog/atguigu-bin"
注意:新建的文件夾需要使用mysql用戶,使用下面的命令即可。
chown -R -v mysql:mysql binlog
方式2:臨時性方式
如果不希望通過修改配置文件并重啟的方式設置二進制日志的話,還可以使用如下指令,需要注意的是在mysql8中只有 會話級別
的設置,沒有了global級別的設置。
# global 級別
mysql> set global sql_log_bin=0;
ERROR 1228 (HY000): Variable 'sql_log_bin' is a SESSION variable and can`t be used
with SET GLOBAL
# session級別
mysql> SET sql_log_bin=0;
Query OK, 0 rows affected (0.01 秒)
5.3 查看日志
當MySQL創(chuàng)建二進制日志文件時,先創(chuàng)建一個以“filename”為名稱、以“.index”為后綴的文件,再創(chuàng)建一個以“filename”為名稱、以“.000001”為后綴的文件。
MySQL服務 重新啟動一次
,以“.000001”為后綴的文件就會增加一個,并且后綴名按1遞增。即日志文件的個數與MySQL服務啟動的次數相同;如果日志長度超過了 max_binlog_size
的上限(默認是1GB),就會創(chuàng)建一個新的日志文件。
查看當前的二進制日志文件列表及大小。指令如下:
mysql> SHOW BINARY LOGS;
+--------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+--------------------+-----------+-----------+
| atguigu-bin.000001 | 156 | No |
+--------------------+-----------+-----------+
1 行于數據集 (0.02 秒)
下面命令將行事件以 偽SQL的形式
表現(xiàn)出來
mysqlbinlog -v "/var/lib/mysql/binlog/atguigu-bin.000002"
#220105 9:16:37 server id 1 end_log_pos 324 CRC32 0x6b31978b Query thread_id=10
exec_time=0 error_code=0
SET TIMESTAMP=1641345397/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0,
@@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb3 *//*!*/;
SET
@@session.character_set_client=33,@@session.collation_connection=33,@@session.collatio
n_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
BEGIN
/*!*/;
# at 324
#220105 9:16:37 server id 1 end_log_pos 391 CRC32 0x74f89890 Table_map:
`atguigu14`.`student` mapped to number 85
# at 391
#220105 9:16:37 server id 1 end_log_pos 470 CRC32 0xc9920491 Update_rows: table id
85 flags: STMT_END_F
BINLOG '
dfHUYRMBAAAAQwAAAIcBAAAAAFUAAAAAAAEACWF0Z3VpZ3UxNAAHc3R1ZGVudAADAw8PBDwAHgAG
AQEAAgEhkJj4dA==
dfHUYR8BAAAATwAAANYBAAAAAFUAAAAAAAEAAgAD//8AAQAAAAblvKDkuIkG5LiA54+tAAEAAAAL
5byg5LiJX2JhY2sG5LiA54+tkQSSyQ==
'/*!*/;
### UPDATE `atguigu`.`student`
### WHERE
### @1=1
### @2='張三'
### @3='一班'
### SET
### @1=1
### @2='張三_back'
### @3='一班'
# at 470
#220105 9:16:37 server id 1 end_log_pos 501 CRC32 0xca01d30f Xid = 15
COMMIT/*!*/;
前面的命令同時顯示binlog格式的語句,使用如下命令不顯示它
mysqlbinlog -v --base64-output=DECODE-ROWS "/var/lib/mysql/binlog/atguigu-bin.000002"
#220105 9:16:37 server id 1 end_log_pos 324 CRC32 0x6b31978b Query thread_id=10
exec_time=0 error_code=0
SET TIMESTAMP=1641345397/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0,
@@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb3 *//*!*/;
SET
@@session.character_set_client=33,@@session.collation_connection=33,@@session.collatio
n_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
BEGIN
/*!*/;
# at 324
#220105 9:16:37 server id 1 end_log_pos 391 CRC32 0x74f89890 Table_map:
`atguigu14`.`student` mapped to number 85
# at 391
#220105 9:16:37 server id 1 end_log_pos 470 CRC32 0xc9920491 Update_rows: table id
85 flags: STMT_END_F
### UPDATE `atguigu14`.`student`
### WHERE
### @1=1
### @2='張三'
### @3='一班'
### SET
### @1=1
### @2='張三_back'
### @3='一班'
# at 470
#220105 9:16:37 server id 1 end_log_pos 501 CRC32 0xca01d30f Xid = 15
關于mysqlbinlog工具的使用技巧還有很多,例如只解析對某個庫的操作或者某個時間段內的操作等。簡單分享幾個常用的語句,更多操作可以參考官方文檔。
# 可查看參數幫助
mysqlbinlog --no-defaults --help
# 查看最后100行
mysqlbinlog --no-defaults --base64-output=decode-rows -vv atguigu-bin.000002 |tail
-100
# 根據position查找
mysqlbinlog --no-defaults --base64-output=decode-rows -vv atguigu-bin.000002 |grep -A
20 '4939002'
上面這種辦法讀取出binlog日志的全文內容比較多,不容易分辨查看到pos點信息,下面介紹一種更為方便的查詢命令:
mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
-
IN 'log_name'
:指定要查詢的binlog文件名(不指定就是第一個binlog文件) -
FROM pos
:指定從哪個pos起始點開始查起(不指定就是從整個文件首個pos點開始算) -
LIMIT [offset]
:偏移量(不指定就是0) -
row_count
:查詢總條數(不指定就是所有行)
mysql> show binlog events in 'atguigu-bin.000002';
+--------------------+-----+----------------+-----------+-------------+---------------
--------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info
|
+--------------------+-----+----------------+-----------+-------------+---------------
--------------------------------------------------------------+
| atguigu-bin.000002 | 4 | Format_desc | 1 | 125 | Server ver:
8.0.26, Binlog ver: 4 |
| atguigu-bin.000002 | 125 | Previous_gtids | 1 | 156 |
|
| atguigu-bin.000002 | 156 | Anonymous_Gtid | 1 | 235 | SET
@@SESSION.GTID_NEXT= 'ANONYMOUS' |
| atguigu-bin.000002 | 235 | Query | 1 | 324 | BEGIN
|
| atguigu-bin.000002 | 324 | Table_map | 1 | 391 | table_id: 85
(atguigu14.student) |
| atguigu-bin.000002 | 391 | Update_rows | 1 | 470 | table_id: 85
flags: STMT_END_F |
| atguigu-bin.000002 | 470 | Xid | 1 | 501 | COMMIT /*
xid=15 */ |
| atguigu-bin.000002 | 501 | Anonymous_Gtid | 1 | 578 | SET
@@SESSION.GTID_NEXT= 'ANONYMOUS' |
| atguigu-bin.000002 | 578 | Query | 1 | 721 | use
`atguigu14`; create table test(id int, title varchar(100)) /* xid=19 */ |
| atguigu-bin.000002 | 721 | Anonymous_Gtid | 1 | 800 | SET
@@SESSION.GTID_NEXT= 'ANONYMOUS' |
| atguigu-bin.000002 | 800 | Query | 1 | 880 | BEGIN
|
| atguigu-bin.000002 | 880 | Table_map | 1 | 943 | table_id: 89
(atguigu14.test) |
| atguigu-bin.000002 | 943 | Write_rows | 1 | 992 | table_id: 89
flags: STMT_END_F |
| atguigu-bin.000002 | 992 | Xid | 1 | 1023 | COMMIT /*
xid=21 */
+--------------------+-----+----------------+-----------+-------------+---------------
--------------------------------------------------------------+
14 行于數據集 (0.02 秒)
上面我們講了這么多都是基于binlog的默認格式,binlog格式查看
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 行于數據集 (0.02 秒)
除此之外,binlog還有2種格式,分別是Statement
和Mixed
- Statement
每一條會修改數據的sql都會記錄在binlog中。
優(yōu)點:不需要記錄每一行的變化,減少了binlog日志量,節(jié)約了IO,提高性能。 - Row
5.1.5版本的MySQL才開始支持row level 的復制,它不記錄sql語句上下文相關信息,僅保存哪條記錄被修改。
優(yōu)點:row level 的日志內容會非常清楚的記錄下每一行數據修改的細節(jié)。而且不會出現(xiàn)某些特定情況下的存儲過程,或function,以及trigger的調用和觸發(fā)無法被正確復制的問題。 - Mixed
從5.1.8版本開始,MySQL提供了Mixed格式,實際上就是Statement與Row的結合。
詳細情況,下章講解。
5.4 使用日志恢復數據
mysqlbinlog恢復數據的語法如下:
mysqlbinlog [option] filename|mysql –uuser -ppass;
這個命令可以這樣理解:使用mysqlbinlog命令來讀取filename中的內容,然后使用mysql命令將這些內容恢復到數據庫中。
-
filename
:是日志文件名。 -
option
:可選項,比較重要的兩對option參數是–start-date、–stop-date 和 --start-position、–stop-position。-
--start-date 和 --stop-date
:可以指定恢復數據庫的起始時間點和結束時間點。 -
--start-position和--stop-position
:可以指定恢復數據的開始位置和結束位置。
注意:使用mysqlbinlog命令進行恢復操作時,必須是編號小的先恢復,例如atguigu-bin.000001必須在atguigu-bin.000002之前恢復。
-
5.5 刪除二進制日志
MySQL的二進制文件可以配置自動刪除,同時MySQL也提供了安全的手動刪除二進制文件的方法。PURGE MASTER LOGS
只刪除指定部分的二進制日志文件, RESET MASTER
刪除所有的二進制日志文件。具體如下:
1. PURGE MASTER LOGS:刪除指定日志文件
PURGE MASTER LOGS語法如下:
PURGE {MASTER | BINARY} LOGS TO ‘指定日志文件名’
PURGE {MASTER | BINARY} LOGS BEFORE ‘指定日期’
5.6 其它場景
二進制日志可以通過數據庫的 全量備份
和二進制日志中保存的 增量信息
,完成數據庫的 無損失恢復
。但是,如果遇到數據量大、數據庫和數據表很多(比如分庫分表的應用)的場景,用二進制日志進行數據恢復,是很有挑戰(zhàn)性的,因為起止位置不容易管理。
在這種情況下,一個有效的解決辦法是 配置主從數據庫服務器
,甚至是 一主多從
的架構,把二進制日志文件的內容通過中繼日志,同步到從數據庫服務器中,這樣就可以有效避免數據庫故障導致的數據異常等問題。
6. 再談二進制日志(binlog)
6.1 寫入機制
binlog的寫入時機也非常簡單,事務執(zhí)行過程中,先把日志寫到 binlog cache
,事務提交的時候,再
把binlog cache寫到binlog文件中。因為一個事務的binlog不能被拆開,無論這個事務多大,也要確保一
次性寫入,所以系統(tǒng)會給每個線程分配一個塊內存作為binlog cache。
write和fsync的時機,可以由參數 sync_binlog 控制,默認是 0 。為0的時候,表示每次提交事務都只write,由系統(tǒng)自行判斷什么時候執(zhí)行fsync。雖然性能得到提升,但是機器宕機,page cache里面的
binglog 會丟失。如下圖:
為了安全起見,可以設置為 1
,表示每次提交事務都會執(zhí)行fsync,就如同redo log 刷盤流程
一樣。
最后還有一種折中方式,可以設置為N(N>1),表示每次提交事務都write,但累積N個事務后才fsync。
在出現(xiàn)IO瓶頸的場景里,將sync_binlog設置成一個比較大的值,可以提升性能。同樣的,如果機器宕機,會丟失最近N個事務的binlog日志。
6.2 binlog與redolog對比
- redo log 它是
物理日志
,記錄內容是“在某個數據頁上做了什么修改”,屬于 InnoDB 存儲引擎層產生的。 - 而 binlog 是
邏輯日志
,記錄內容是語句的原始邏輯,類似于“給 ID=2 這一行的 c 字段加 1”,屬于MySQL Server 層。
6.3 兩階段提交
在執(zhí)行更新語句過程,會記錄redo log與binlog兩塊日志,以基本的事務為單位,redo log在事務執(zhí)行過程中可以不斷寫入,而binlog只有在提交事務時才寫入,所以redo log與binlog的 寫入時機
不一樣。redo log與binlog兩份日志之間的邏輯不一致,會出現(xiàn)什么問題?
由于binlog沒寫完就異常,這時候binlog里面沒有對應的修改記錄。
為了解決兩份日志之間的邏輯一致問題,InnoDB存儲引擎使用兩階段提交
方案。
使用兩階段提交
后,寫入binlog時發(fā)生異常也不會有影響
另一個場景,redo log設置commit階段發(fā)生異常,那會不會回滾事務呢?
并不會回滾事務,它會執(zhí)行上圖框住的邏輯,雖然redo log是處于prepare階段,但是能通過事務id找到對應的binlog日志,所以MySQL認為是完整的,就會提交事務恢復數據。
7. 中繼日志(relay log)
7.1 介紹
中繼日志只在主從服務器架構的從服務器上存在
。從服務器為了與主服務器保持一致,要從主服務器讀取二進制日志的內容,并且把讀取到的信息寫入 本地的日志文件
中,這個從服務器本地的日志文件就叫中繼日志
。然后,從服務器讀取中繼日志,并根據中繼日志的內容對從服務器的數據進行更新,完成主從服務器的 數據同步
。
搭建好主從服務器之后,中繼日志默認會保存在從服務器的數據目錄下。
文件名的格式是: 從服務器名 -relay-bin.序號
。中繼日志還有一個索引文件: 從服務器名 -relaybin.index
,用來定位當前正在使用的中繼日志。
7.2 查看中繼日志
中繼日志與二進制日志的格式相同,可以用 mysqlbinlog
工具進行查看。下面是中繼日志的一個片段:
SET TIMESTAMP=1618558728/*!*/;
BEGIN
/*!*/;
# at 950
#210416 15:38:48 server id 1 end_log_pos 832 CRC32 0xcc16d651 Table_map:
`atguigu`.`test` mapped to number 91
# at 1000
#210416 15:38:48 server id 1 end_log_pos 872 CRC32 0x07e4047c Delete_rows: table id
91 flags: STMT_END_F -- server id 1 是主服務器,意思是主服務器刪了一行數據
BINLOG '
CD95YBMBAAAAMgAAAEADAAAAAFsAAAAAAAEABGRlbW8ABHRlc3QAAQMAAQEBAFHWFsw=
CD95YCABAAAAKAAAAGgDAAAAAFsAAAAAAAEAAgAB/wABAAAAfATkBw==
'/*!*/;
# at 1040
這一段的意思是,主服務器(“server id 1”)對表 atguigu.test 進行了 2 步操作:
定位到表 atguigu.test 編號是 91 的記錄,日志位置是 832;
刪除編號是 91 的記錄,日志位置是 872。
7.3 恢復的典型錯誤
如果從服務器宕機,有的時候為了系統(tǒng)恢復,要重裝操作系統(tǒng),這樣就可能會導致你的 服務器名稱
與之前 不同
。而中繼日志里是 包含從服務器名
的。在這種情況下,就可能導致你恢復從服務器的時候,無法從宕機前的中繼日志里讀取數據,以為是日志文件損壞了,其實是名稱不對了。文章來源:http://www.zghlxwxcb.cn/news/detail-447916.html
解決的方法也很簡單,把從服務器的名稱改回之前的名稱。文章來源地址http://www.zghlxwxcb.cn/news/detail-447916.html
到了這里,關于MySQL基礎(三十六)其他數據庫日志的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!