课程回顾:
事务的生命周期管理
标准的事务控制语句
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. 慢日志