課程回顧:
事務的生命週期管理
標準的事務控制語句
begin
DML #標準的事務語句
commit
rollback
autocommit機制
觸發前提:參數爲1----開啓了
沒有顯示的觸發 begin操作和commit操作
特點:每次執行任何的DML語句時,會自動添加begin,結束時commit
隱式提交
事務期間出現了DML時,自動提交
隱式回滾
客戶端連接關閉、實例關閉、資源衝突時(死鎖時)
事務的‘隔離級別
RU 讀未提交 可能出現問題:髒讀、不可重複讀、幻讀
RC 讀以提交 可能出現問題:不可重複讀、幻讀
RR 可重複讀 可能出現問題: 有時會出現“幻讀”,大部分情況可以預防
SR 串行化 完全隔離 但是併發性不好
事務的工作流程原理:
專業名詞介紹
redo
( redo log、log buffer) 內存數據的變化日誌
page
(ibd 磁盤page、 buffer pool 內存配置) 存儲數據行和索引
undo
(5.7默認在ibdataN中,可以配置爲獨立;undo的段(128段);96個段在undo中 ;32個臨時表空間使用) 存儲回滾信息
LSN
:日誌序列號 (從小到大增長的,增長的幅度取決於日誌的字節量)存儲位置(redo log buffer 當前LSN;redo log flush log LSN; 磁盤數據頁的LSN CKPT LSN)
數據庫宕機啓動時,flush log 的LSN 和CKPT LSN 對比 進行判斷是否要進行恢復數據
WAL (日誌優先寫)
wwrite ahead log
redo 優先於數據頁落盤
dirtry 髒頁
在buffer中被修改過的數據頁,還有落盤的
checkpoit (異步落盤)
作用:較爲及時的將數據頁刷寫到磁盤上
觸發條件:1、sharp checkpoint 正常關閉數據庫時觸發
2、fuzzy checkpoint master thread checkpoint 大約每秒或者每十秒觸發一次
觸發的參數
mysql> show variables like '%innodb_io%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| innodb_io_capacity | 200 | 每次200個
| innodb_io_capacity_max | 2000 | 不能超過2000
+------------------------+-------+
2 rows in set (0.00 sec)
3、fuzzy flush_lru_list__checkpoint 介紹:buffer pool 中的LRU內存鏈表可用內存頁數 最近最少使用原則內存鏈表
show variables like '%lru%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_lru_scan_depth | 1024 |
+-----------------------+-------+
1 row in set (0.01 sec)
當低於這幾個值的時候,就會觸發CKPT
async/sync flush checkpoint (75% 軟限制 async)
(90% 硬限制 sync)
checkpoint_age=redo_lsn-checkpoint_lsn
dirty page too much checkpoint
(buffer pool 髒頁太多的時候,默認75%) (innodb_max_dirty_pages_pct)
mysql> show variables like '%innodb_max_%';
+--------------------------------+-----------+
| Variable_name | Value |
+--------------------------------+-----------+
| innodb_max_dirty_pages_pct | 75.000000 |
回滾信息
DB_TRX_ID 事務編號
DB_ROLL_PTR undo回滾信息
redo log重做日誌如何應用
作用:提供ACID的,主要是D的特性,對AC也有關聯,CR過程中提供前滾功能
記錄的是,內存數據頁的變化,LSN號碼生成
redo日誌 由於有批量刷新的功能,有部分未提交的事務,二redo也會被寫到磁盤,使用commit標籤進行區分。
undo log 回滾日誌如何應用
作用:ACID中,主要提供A的特性,對於C和I也有影響;在CR過程中提供回滾功能。
事務中C的特性怎麼保證
CR
DWB
髒頁控制參數
事務中的I的特性怎麼保證?
隔離級別:讀隔離性
RU : 髒讀 、 不可重複讀 、幻讀
RC : 不可重複讀、幻讀
RR :有可能會出現幻讀。
SR(SE) :事務串行工作。
鎖的機制 寫的隔離
作用:保護併發訪問資源
保護的資源分類:
latch (栓鎖):rwlock、mutex 主要保護內存資源
MDL:metadata lock 元數據鎖(DDL操作的)
table_lock : 表級鎖
lock table t1 read;
mysqldump\XBK(PBK):備份非innodb數據時,觸發FTWRL全局鎖表(global)
行鎖升級爲表鎖:默認情況下innodb的鎖都是行鎖,如果是修改全表的所有行升級時,會升級爲表鎖。
row lock:默認鎖粒度是行級鎖,加鎖的方式都是在索引上加鎖的
record lock 記錄鎖,在聚簇索引加鎖
gap lock 間隙鎖 在輔助索引加鎖 (輔助索引的鍵值範圍)
next lock GAP+record 所有(輔助索引加鎖+聚簇索引加鎖)索引加鎖 下鍵鎖。
RC級別只存在record lock 鎖
RR級別中存在 gap lock 和 next lock 防止幻讀。(雖然RR級別也可能出現幻讀,但是很少出現)
什麼是幻讀,RR級別又是如何防止幻讀的?
演示:不可重複讀現象
第一步:查看隔離級別
select @@transact
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED |
+-------------------------+
1 row in set (0.00 sec)
RC級別下幻讀現象演示:
準備工作:
mysql> alter table t1 add index(num);
[root@db01 ~]# mysqldump test t1 >/tmp/t1.sql
session A :
第一步:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 1 | aa |
| 2 | 3 | c |
| 3 | 6 | d |
| 4 | 7 | x |
| 5 | 11 | a |
| 6 | 23 | c |
| 7 | 36 | d |
| 8 | 37 | x |
| 9 | 51 | as |
| 10 | 63 | hc |
| 11 | 76 | ds |
| 12 | 87 | xyz |
+----+-----+------+
12 rows in set (0.00 sec)
第三步:
mysql> update t1 set num=10 where num<10;
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4 Changed: 4 Warnings: 0
第五步:
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 10 | aa |
| 2 | 10 | c |
| 3 | 10 | d |
| 4 | 10 | x |
| 5 | 11 | a |
| 6 | 23 | c |
| 7 | 36 | d |
| 8 | 37 | x |
| 9 | 51 | as |
| 10 | 63 | hc |
| 11 | 76 | ds |
| 12 | 87 | xyz |
| 13 | 5 | aaa |
+----+-----+------+
Session B:
第二步:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 1 | aa |
| 2 | 3 | c |
| 3 | 6 | d |
| 4 | 7 | x |
| 5 | 11 | a |
| 6 | 23 | c |
| 7 | 36 | d |
| 8 | 37 | x |
| 9 | 51 | as |
| 10 | 63 | hc |
| 11 | 76 | ds |
| 12 | 87 | xyz |
+----+-----+------+
12 rows in set (0.00 sec)
第四步:
mysql> insert into t1(num,name) values(5,'aaa');
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
演示二:RC讀以提交 級別下幻讀現象演示:
在事務工作期間,SQL層已經執行了,只是沒有落盤,在還沒有提交之前,又一個窗口進行插入操作,並且已經commit,提交了。此時第一個SQL層再commit,會導致新插入的數據即使滿足第一條語句的條件,但是還是不會作用到這個語句上。
打開兩個會話窗口
RC級別下不可重讀現象演示:
vim /etc/my.cnf
#添加隔離級別參數:
transaction_isolation=READ-COMMITTED
#重啓數據庫
[root@db01 ~]# /etc/init.d/mysqld restart
打開兩個會話窗口:
sessionA:
第一步:
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED |
+-------------------------+
1 row in set (0.00 sec)
第三步:
mysql> create database test charset utf8mb4;
mysql> use test;
mysql> create table t1 (id int primary key auto_increment,num int not null , name varchar(20) not null);
mysql> insert into t1(num,name) values(1,'a'),(3,'c'),(6,'d'),(7,'x');
mysql> insert into t1(num,name) values(11,'a'),(23,'c'),(36,'d'),(37,'x'');
mysql> insert into t1(num,name) values(51,'as'),(63,'hc'),(76,'ds'),(87,'x','xyz');
mysql> commit;
mysql> select * from t1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 1 | a |
| 2 | 3 | c |
| 3 | 6 | d |
| 4 | 7 | x |
| 5 | 11 | a |
| 6 | 23 | c |
| 7 | 36 | d |
| 8 | 37 | x |
| 9 | 51 | as |
| 10 | 63 | hc |
| 11 | 76 | ds |
| 12 | 87 | xyz |
+----+-----+------+
第五步:
mysql> begin;
第七步:
mysql> update t1 set name='aa' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
=================================================
sessinB:
第二步:
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED |
+-------------------------+
1 row in set (0.00 sec)
第四步:
mysql> use test;
mysql> select * from test.t1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 1 | a |
| 2 | 3 | c |
| 3 | 6 | d |
| 4 | 7 | x |
| 5 | 11 | a |
| 6 | 23 | c |
| 7 | 36 | d |
| 8 | 37 | x |
| 9 | 51 | as |
| 10 | 63 | hc |
| 11 | 76 | ds |
| 12 | 87 | xyz |
+----+-----+------+
12 rows in set (0.00 sec)
第六步:
mysql> begin;
mysql> select * from t1 where id=1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 1 | a |
+----+-----+------+
1 row in set (0.00 sec)
第八步:
mysql> select * from t1 where id=1;
+----+-----+------+
| id | num | name |
+----+-----+------+
| 1 | 1 | aa |
+----+-----+------+
1 row in set (0.00 sec)
==================================
RR級別:防止幻讀的演示
和鎖有關。導致在這個行進行commit之前,都會有鎖。如果此時有人在另外一個窗口進行插入操作,會導致卡住,不能進行修改。
防止幻讀:前提是,1、where後的條件需要有輔助索引。如果沒有輔助索引,就會出現行級鎖升級爲表級鎖;2、RR級別纔會有gap鎖(鍵值範圍)
功能上:
IS 不研究
S 讀鎖; select * from t1 lock in shared mode; 不研究
IX 意向排它鎖 針對表 ; select * from t1 for update;
X 排它鎖 ,寫鎖 針對行
IX 針對表 X 針對行 ;IX是X的前提,如果沒法對該行的表進行 表的意向鎖 則不能對行進行排他鎖
加鎖的行,不能進行併發處理了。
IX 針對表 X 針對行 ;IX是X的前提,如果沒法對該行的表進行 表的意向鎖 則不能對行 進行的排他鎖
哪些鎖不能同時進行,也就是鎖的兼容性問題
MVCC:多版本併發控制(針對讀操作)
每個事物都需要經歷兩個階段:
讀和寫
不管是進行什麼操作都需要:
讀的步驟
寫的步驟
MVCC是針對讀的操作,進行併發控制,因爲讀是不需要加鎖的。寫的操作是由鎖來控制的,不屬於MVCC管理範圍。
利用樂觀鎖機制,實現非鎖定讀取
什麼是樂觀鎖
到時候後再說
讀的時候就是樂觀鎖
什麼是悲觀鎖
一開始就鎖上
寫的操作時,主要悲觀鎖
read view 版本號集合
trx1
begin;
dml1 —在做第一個查詢的時候,當前事物,獲取當前系統最新的;RV1版本快照
dml2 —生成一個RV2的版本快照
select 查詢RV2快照的數據情況,當commit時 會被更新到系統的最新快照
commit;
先說一個redo view
RC級別
一個快照可以讀取到另一個已經提交的事務的全新快照
RR級別
一個查詢 生成一個快照,一直伴隨着事務生命週期結束。
trx1: 不可重複讀的現象
快照技術是由undo log來提供
總結:MVCC
1、MVCC採用樂觀鎖機制實現非鎖定讀取
2、MVCC在RC級別下,事務可以立即讀取到另一個事務已經提交的最新的redo view
3、MVCC在RR級別下,事務中從第一次查詢開始,生成了一個redo view(只有這一個版本) 一直伴隨到事務結束
日誌管理
錯誤日誌
作用:記錄數據庫啓動以來,狀態、警告、報錯。診斷數據庫報錯問題
默認:開啓狀態。存放在數據目錄下(/data/3306/data/.err)
查詢配置
mysql> select @@log_error;
+-------------+
| @@log_error |
+-------------+
| ./db01.err |
+-------------+
1 row in set (0.00 sec)
mysql> select @@datadir;
+------------------+
| @@datadir |
+------------------+
| /data/3306/data/ |
+------------------+
1 row in set (0.00 sec)
修改配置
修改配置:
[root@db01 ~]# mkdir -p /data/3306/logs
[root@db01 ~]# chown -R mysql.mysql /data/*
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
#添加:
log_error=/data/3306/logs/mysql.err
[root@db01 logs]# cat /etc/my.cnf
[mysqld]
log_error=/data/3306/logs/mysql.err 這個日誌文件的屬主屬組是mysql且是touch創建出來的,然後數據
# 重啓報錯
[root@db01 ~]# /etc/init.d/mysqld restart
++++++++++++++++++++++
Shutting down MySQL.. SUCCESS!
Starting MySQL.2020-05-09T06:51:36.457401Z mysqld_safe error: log-error set to '/data/3306/logs/mysql.err', however file don't exists. Create writable for user 'mysql'.
ERROR! The server quit without updating PID file (/data/3306/data/db01.pid).
++++++++++++++++++++++
[root@db01 ~]# touch /data/3306/logs/mysql.err
[root@db01 ~]# chown -R mysql.mysql /data/*
# 重新啓動
[root@db01 ~]# /etc/init.d/mysqld restart
報錯是因爲touch的日誌文件沒有設置屬主屬組爲mysql
查看日誌
# 模擬故障
[root@db01 ~]# chown -R root.root /data/3306/data/ibdata1
[root@db01 ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL.. ERROR! The server quit without updating PID file (/data/3306/data/db01.pid).
[root@db01 ~]#
# 排查思路 :
[ERROR] 行:
2020-05-09T06:56:09.226056Z 0 [ERROR] InnoDB: The innodb_system data file 'ibdata1' must be writable
日誌切割
[root@db01 logs]# ll
total 32
-rw-r--r-- 1 mysql mysql 31445 May 9 03:04 mysql.err
[root@db01 logs]# cp mysql.err mysql.err_`date +%F`
[root@db01 logs]# ll
total 64
-rw-r--r-- 1 mysql mysql 31445 May 9 03:04 mysql.err
-rw-r--r-- 1 root root 31445 May 9 03:06 mysql.err_2020-05-09
[root@db01 logs]# > mysql.err
grep -r 'ERROR' mysql.err_2020-05-09
二進制日誌(binlog)*****
作用:
1、用來做數據恢復 PTR 基於時間點的恢復
2、主從複製依賴於二進制日誌
日誌內容介紹:
記錄數據庫修改類的操作(邏輯日誌)
DML:insert update delete
DDL:create drop alter trucate
DCL:grant revoke lock(鎖表語句)
配置方法:
8.0版本之前默認不開啓
mysql> select @@log_bin;
mysql> select @@log_bin_basename;
mysql> select @@server_id;
配置基礎參數
vim /etc/my.cnf
[mysqld]
server_id=6 主機ID 在主從複製會使用
log_bin=/data/3306/logs/mysql-bin 開關+文件路徑+文件名前綴 最終格式:mysql-bin.001 002 003
重啓生效
[root@db01 logs]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL.. SUCCESS!
bin log內容的記錄格式
事件(event)的方式記錄
最小的記錄單元
每個事件:
1、事件描述 事件戳、server_id、加密方式、開始的位置(satrt_pos)、結束位置點(end_pos)
2、事件內容 修改類的操作(DDL、DML)SQL語句 或者 數據行變化。
重點關注:
開始位置點(satrt_pos)
結束位置點 (end_pos)
事件內容
二進制日誌事件內容格式
mysql> select @@binlog_format;
+-----------------+
| @@binlog_format |
+-----------------+
| ROW |
+-----------------+
1 row in set (0.00 sec)
作用:
對於DDL、DCL語句 直接將SQL本身記錄到binlog中
對於DML:insert update delete 受到binlog_format 參數控制
SBR:statement :語句模式,之前版本,默認模式
RBR: ROW 行記錄模式。5.7之後,默認模式
MBR:miexd 混合模式
RBR和SBR的區別:
SBR:記錄SQL語句本身 RBR:記錄的是100個數據行的變化 記錄的比較準確。
SBR 日誌量比較少 RBR日誌量比較多 並且SBR記錄的不夠準確,列如:使用now()函數,直接記錄語句本身的話,時間就不一樣了。
binlog的應用
1、日誌文件情況查詢
查看日誌文件是否存在
mysql> show binary logs; 查看所有的日誌文件信息
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 154 |
+------------------+-----------+
1 row in set (0.00 sec)
刷新日誌(每刷新一次,會出現一個日誌文件)
mysql> flush logs;產生一個新的日誌
查看當前正在使用的日誌文件
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
內容查詢
mysql> show binlog events in 'mysql-bin.000005';
關注黃色
ROW格式,所以需要使用這個看
查看binlog日誌,也可以進行截取binlog日誌
[root@db01 logs]# mysqlbinlog /data/3306/logs/mysql-bin.000005
# at 324
#200509 3:50:10 server id 6 end_log_pos 389 CRC32 0x2d401b39 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 389
#200509 3:50:10 server id 6 end_log_pos 487 CRC32 0x66e33e19 Query thread_id=3 exec_time=0 error_code=0
use `ku`/*!*/;
SET TIMESTAMP=1589010610/*!*/;
create table biao (id int)
/*!*/;
# at 487
插入操作的兩種方式
查看日誌內容
[root@db01 logs]# mysqlbinlog /data/3306/logs/mysql-bin.000005
#### create table 日誌內容
# at 388
#200509 15:49:59 server id 6 end_log_pos 484 CRC32 0x8b05dfaf Query thread_id=3 exec_time=0 error_code=0
use `ku`/*!*/;
create table biao (id int)
/*!*/;
# at 484
insert 操作的日誌內容
# at 549
#200509 15:50:36 server id 6 end_log_pos 619 CRC32 0x515eec96 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1589010636/*!*/;
BEGIN
/*!*/;
# at 619
#200509 15:50:36 server id 6 end_log_pos 664 CRC32 0xedfb82fb Table_map: `ku`.`biao` mapped to number 108
# at 664
#200509 15:50:36 server id 6 end_log_pos 704 CRC32 0x5762132e Write_rows: table id 108 flags: STMT_END_F
BINLOG '
zGC2XhMGAAAALQAAAJgCAAAAAGwAAAAAAAEAAmt1AARiaWFvAAEDAAH7gvvt
zGC2Xh4GAAAAKAAAAMACAAAAAGwAAAAAAAEAAgAB//4BAAAALhNiVw=='
/*!*/;
# at 704
#200509 15:50:40 server id 6 end_log_pos 735 CRC32 0xb06a212b Xid = 24
COMMIT/*!*/;
[root@db01 logs]# mysqlbinlog --base64-output=decode-rows -vv /data/3306/logs/mysql-bin.000005
.....略。
BEGIN
/*!*/;
# at 619
#200509 15:50:36 server id 6 end_log_pos 664 CRC32 0xedfb82fb Table_map: `ku`.`biao` mapped to number 108
# at 664
#200509 15:50:36 server id 6 end_log_pos 704 CRC32 0x5762132e Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `ku`.`biao`
### SET
### @1=1 /* INT meta=0 nullable=1 is_null=0 */
# at 704
#200509 15:50:40 server id 6 end_log_pos 735 CRC32 0xb06a212b Xid = 24
COMMIT/*!*/;
binlog日誌翻譯一下
[root@db01 logs]# mysqlbinlog --base64-output=decode-rows -vv /data/3306/logs/mysql-bin.000005
二進制日誌的截取以及恢復演練
故障模擬
mysql> drop database ku;
Query OK, 1 row affected (0.14 sec)
binlog日誌截取及恢復演練
故障模擬
mysql> drop database ku;
Query OK, 1 row affected (0.01 sec)
需要恢復ku的所有數據到刪庫之前
思路:
1、截取從建庫以來到刪除庫之前的所有binlog
2、將截取的日誌進行回放
思路:
1、截取從建庫以來到刪除庫之前的所有binlog
起點:建庫的位置點(position)
終點:刪庫的位置點(position)
2、將截取的日誌進行回放
[root@db01 logs]# mysqlbinlog --start-position=219 --stop-position=707 /data/3306/logs/mysql-bin.000005 > /tmp/bin.sql
source /tmp/bin.sql;
mysql> set sql_log_bin=0;關閉當前窗口的二進制binlog日誌
Query OK, 0 rows affected (0.00 sec)
別忘記恢復完以後,在設置回來
mysql> set sql_log_bin=1;
如果是生產中會有什麼痛點?
1、如果需要的日誌在多文件中,怎麼截取?
恢復方法:
方法一:多個文件 分段截取
–start-position 開始
–stop-position 結束
方法二:按照時間戳截取
起點:建庫的時間戳
200509 5:12:49
200509 5:15:43
方法三:gtid 最靠譜的方法
1、找起點
2、找終點
3、截取日誌
2、binlog日誌屬於全局日誌,如果在對一個庫進行操作時,其他的庫的操作記錄也會記錄下來,怎麼排除掉。
3、日誌中有一百萬行日誌,怎麼快速找到drop的位置點
4、如果刪除的庫是在兩年前創建的,這種情況怎麼辦?
彩蛋:
思考一下:如果生產中會有什麼痛點?
1. 需要的日誌在多個文件中,怎麼截取?
# 場景模擬:
mysql> show master status ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 886 | | | |
+------------------+----------+--------------+------------------+-------------------+
mysql> create database tongdian charset=utf8mb4;
mysql> use tongdian
mysql> create table t1 (id int);
mysql> flush logs;
mysql> show master status ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000006 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
mysql> insert into t1 values(1),(2),(3);
mysql> commit;
mysql> flush logs;
mysql> show master status ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000007 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
mysql> create table t2(id int);
mysql> insert into t2 values(1),(2),(3);
mysql> commit;
mysql> flush logs;
mysql> show master status ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000008 | 154 | | | |
mysql> insert into t2 values(11),(22),(33);
mysql> commit;
mysql> drop database tongdian;
# 恢復方法:
方法1: 分段截取
--start-position --stop-position
方法2: 時間戳截取
1. 找起點 :建庫的時間戳
(1) 起點: postion 號
mysql> show binlog events in 'mysql-bin.000005';
| mysql-bin.000005 | 951 | Query | 6 | 1073 | create database tongdian charset=utf8mb4 |
(2) 通過position 過濾時間戳
[root@db01 logs]# mysqlbinlog --start-position=951 --stop-position=1073 mysql-bin.000005 |grep -A 1 '^\#\ at\ 951'
# at 951
#200509 17:11:23 server id 6 end_log_pos 1073 CRC32 0x220759ef Query thread_id=8 exec_time=0 error_code=0
2. 找終點
[root@db01 logs]# mysql -e "show binlog events in 'mysql-bin.000008'"
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000008 | 4 | Format_desc | 6 | 123 | Server ver: 5.7.28-log, Binlog ver: 4 |
| mysql-bin.000008 | 123 | Previous_gtids | 6 | 154 | |
| mysql-bin.000008 | 154 | Anonymous_Gtid | 6 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 219 | Query | 6 | 295 | BEGIN |
| mysql-bin.000008 | 295 | Table_map | 6 | 344 | table_id: 112 (tongdian.t2) |
| mysql-bin.000008 | 344 | Write_rows | 6 | 394 | table_id: 112 flags: STMT_END_F |
| mysql-bin.000008 | 394 | Xid | 6 | 425 | COMMIT /* xid=114 */ |
| mysql-bin.000008 | 425 | Anonymous_Gtid | 6 | 490 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000008 | 490 | Query | 6 | 594 | drop database tongdian |
mysqlbinlog mysql-bin.000008
[root@db01 logs]# mysqlbinlog mysql-bin.000008
#200509 17:13:52
3. 截取日誌
[root@db01 logs]# mysqlbinlog --start-datetime="2020-05-09 17:11:23" --stop-datetime="2020-05-09 17:14:01" mysql-bin.000005 mysql-bin.000006 mysql-bin.000007 mysql-bin.000008 >/tmp/data.sql
遺留
方法3:gtid (後面講)
2. binlog屬於全局日誌,日誌中有其他庫的操作,怎麼排除掉?
3. binlog中100w個事件,怎麼快速找到drop database的位置點?
4. 比如刪除的庫,建庫是在2年前操作的。這種情況怎麼辦?
3. 慢日誌