1-日志分类

4-日志 - 图1

undo redo后面讲 relaylog到主从的时候讲

1.1-general query log

查询日志是记录mysql的所有日志的文件,如果要记录意味着数据会很大,所以默认是开启的。

查看查询日志的变量相关:

  1. show variables like 'general_log%';

image.png

因为默认是不会开启全部的查询日志的,所以初次去看的时候这个文件是不存在的

开启查询日志:

  1. set global general_log =1;
  2. show variables like 'general_log%';

image.png
随便执行两条sql:

  1. select * from `order` where id =1;
  2. update `order` set order_id = "xxxx" where order_id = "xxxx" ;

查看日志:

  1. cat /var/lib/mysql/ecs-342416-0001.log

image.png

select update都会进入

1.2-error log

  1. show variables like 'log_error%'

image.png

错误日志默认是开启的

之前我们就出现过错误日志,我们直接去看看内容:

  1. cat /var/log/mysql/error.log

image.png

不看不知道,居然有人在扫描我的mysql,所以生产环境一定要设置内网访问做好权限关卡啊!!

1.3-slow query log

慢查询在索引那一小节就讲到过。

  1. show variables like 'slow%';

image.png
image.pngupdate order set order_id = “xxxx” where order_id = “xxxx”; 刚刚我们测试查询日志的sql也进入了,因为我们此时的慢查询sql的时间为0.01s,这条sql没有走索引,进行全表扫描,所以耗时较长。
image.png

1.4-binnary log

1.4.1-binlog文件使用

binnary log就是大家平时说的binlog,二进制日志了。

  1. show variables like 'log_bin%';//查看日志开启状态和日志位置
  2. show variables like 'server_id%';//

server_id 表示当前数据库实例的id,只有同时保持log_bin=ON和server_id>1 binlog才会生效。是因为在主从复制的时候需要标记数据的来源,所以server_id是要是一个大于0的数,且在整个数据库集群中server_id应该唯一,不然数据同步的时候会出现各种问题。

image.png

我这里是mysql8.0 默认就是开启的binlog

在mysql的数据目录下已经有了很多和二进制文件:
image.png
查看binlog内容:

  1. cat /var/lib/mysql/binlog.000031

image.png

全是乱码 因为binlog为二进制需要专门的命令查看

  1. mysqlbinlog /var/lib/mysql/binlog.000031

image.png
或者重定向到文件中也可以

  1. mysqlbinlog /var/lib/mysql/binlog.000030 > binlog-sql-plain-text.sql
  2. wc binlog-sql-plain-text.sql

image.png

一百多万行 下载下来留个底吧 免得以后看:scp root@xx.xx.xx.xx:/root/binlog-sql-plain-text.sql ./

binlog-sql-plain-text.sql

1.4.2-管理binlog文件

列出所有二进制文件

  1. show binary logs;

image.png
当前正在使用的二进制文件:

  1. show master status;

image.png

当前正在使用的是000031这个

切换开启一个新的二进制文件:

  1. flush logs;

在某个特殊的节点我们可能需要手动的操作 来完成日志节点标识 除了手动执行flush logs会重新生成一个日志文件外,还有mysql重启和单个日志文件大于max_binlog_size也会重新开启一个日志文件。

image.png


查看日志文件中的事件:

  1. show binlog events in "binlog.000006";

image.png
从Pos(postion)标记位为447的开始往后看日志事件:

  1. show binlog events in "binlog.000006" from 447;

image.png

删除binlog日志:

  1. reset master

这里我就不演示了 后面我还要做备份还原的

2-备份&还原&恢复

2.1-备份(backup)&还原(restore)

4-日志 - 图20

2.1.1-物理备份&还原

2.1.1.1-cp命令

  1. cp -a /var/lib/mysql /backup

物理备份一般是建议停服,因为在你copy的过程中如果你插入了一条数据,但是刚好这个数据文件copy完成,那么你刚插入的数据就会丢失。
网上都说是停服备份我以为是客观原因只能停服,结果我尝试了在执行这条命令的时候写入和读取操作都是可以进行的。

image.png

假设我们删除了数据库中的db为“taobao”的数据库相关信息:
image.png

  1. rm -rf /var/lib/mysql/taobao
  2. service restart mysql

再去访问的时候表无法访问
image.png

数据库下面“taobao”文件夹已经不在

image.png

我们把刚才备份对应的“taobao”文件copy到mysql下面

  1. cp -a /backup/taobao /var/lib/mysql
  2. service mysql restart

image.png
数据又回来了
image.png
当然你可以删除/var/lib/mysql下面的任何一个文件,然后恢复,甚至全部删除都行。

2.1.2.3-xtrabackup

官方文档:https://docs.percona.com/percona-xtrabackup/8.0/installation/apt_repo.html
percona公司产品,他们的 mysq集群解决方案pcx也很出名。
目前xtrabackup只支持innodb引擎。

  1. wget https://downloads.percona.com/downloads/Percona-XtraBackup-LATEST/Percona-XtraBackup-8.0.26-18/binary/debian/focal/x86_64/percona-xtrabackup-80_8.0.26-18-1.focal_amd64.deb
  2. apt-get install libdbd-mysql-per
  3. dpkg -i percona-xtrabackup-80_8.0.26-18-1.focal_amd64.deb

官方给的那个apt-install的方案的源有点问题 我选择直接下载.deb包安装

image.png

  1. xtrabackup --user=root --password=root123456... --parallel=2 --backup --target-dir=/backup/20220707 --no-timestamp

image.png
目前还不支持mysql8.0,尬住了。。。。。。。

2.1.2-逻辑备份&还原

2.1.2.1-mysqldump

  1. mysqldump -u root -p --databases taobao > taobao.sql;

当然还可以全部数据库备份 备份指定表 或者根据where条件备份某个表的某些数据

备份成功后我删除taobao这个数据库:。
image.png
现在我们进行数据库备份还原

  1. mysql -u root -p taobao < taobao.sql

也可以进入mysql终端 source /backup/taobao.sql效果是一样的

image.png
数据库正在慢慢恢复,因为order表有1千万条数据,所以再等待order表恢复才能继续往下走:
image.png
过了15分钟恢复正常
image.png
order中的一千万条数据也回来了
image.png

mysqldump 在上面的备份命令上默认锁表,只允许select操作不允许其他操作。

  1. mysqldump -u root -p taobao order > order.sql;

此时向数据库insert操作插入数据,一直在等待,说明mysqldump是锁表的
image.png
但是调用api接口访问order表是可以正常访问的(get查询接口),说明mysqldump允许select操作image.png

所以官方也提供了许多其他参数来供你选择,一般来讲最佳方案是:

  1. mysqldump -u root -p --databases taobao
  2. --flush-logs
  3. --master-data=2
  4. --single-transaction
  5. --routines
  6. --triggers> taobao.sql;

这样还是会锁表,只是—master-data=2 —single-transaction两个参数保证了备份时候数据的一致性

—flush-logs 开始备份前先手动刷新二进制文件,做个标识
—master-data=2 记录当前备份操作备份到哪个二进制文件的哪个postion点,方便后续还原
—single-transaction 把当前的备份命令当作事务去执行,不影响其他的crud操作
—routines 备份存储过程
—triggers 备份触发器
需要注意的是这样备份还是会锁表,只不过是保证了数据的一致性。

  1. show binary logs;

image.png

现在的binlog节点是编号为000047

  1. mysqldump -u root -p --databases taobao --flush-logs --master-data=2 --single-transaction --routine --triggers> taobao.sql;

image.png
image.png

表示我备份到了编号为0000048 postion为157的这个位置,大于157之后的就没有备份了

看看在157之后进行了什么操作:

  1. show binlog events in "binlog.000048" from 157;

image.png

INSERT INTO order(order_id,user_id)VALUES (‘32424234234’,32131); 我在备份完成后手动插入了一条数据,二进制文件可以看出对table进行了写入操作

查看具体操作:

  1. mysqlbinlog /var/lib/mysql/binlog.000048 -v

image.png

这对应数据库字段的编号的值,6 7是时间戳因为我数据库字段是时间字段。

image.png
也就是说我们可以基于这个备份恢复到编号为000048的position=157的这个位置的,实现增量备份和数据恢复操作,后面会讲。

2.1.2.2-mysqlpump

mysqlpump是一个支持多线程的备份工具,其他的命令我这先不介绍,介绍多线程备份的命令

  1. #全备份大概30s
  2. mysqldump -u root -p --all-databases > taobao.sql
  3. #全备份大概18s
  4. mysqlpump -u root -p --default-parallelism=10 --parallel-schemas=4 - --all-databases> taobao.sql;

image.png如果数据库中的db够多,差距应该会更大。

2.1.3-全量备份

全量备份就是前面的备份全部数据库内容,不管是cp命令还是mysqldump —all-database 或者xtrabackup都可以做到,就是前面已经实现过的。这里不在过多讲解,只是把命令贴出来:

  1. cp -a /var/lib/mysql /backup
  2. cp -a backup /backup /var/lib/mysql
  1. mysqldump -u root -p --all-databases --flush-logs --master-data=2 --single-transaction --routines --triggers> taobao.sql;
  1. mysqlpump -u root -p --default-parallelism=10 --parallel-schemas=4 - --all-databases> taobao.sql;
  1. 还不支持8.0改天搞个5.7的补上这里。。。

2.1.4-增量备份

2.1.4.1-基于mysqldump的增量备份

假设我们2022-07-07这天有史以来对数据库进行了第一次的备份:

  1. mysqldump -u root -p --databases taobao --flush-logs --master-data=2 --single-transaction --routines --triggers> taobao.sql;

image.png

目前的备份的数据库在binglog.000050 position=157的地方

随着业务的进行,产生了很多的数据:

  1. flush logs;
  2. INSERT INTO `order`(order_id,user_id)VALUES ('00000000000000000000',32131);
  3. INSERT INTO `order`(order_id,user_id)VALUES ('111111111111111111',32131);

后面我们只需要保存binglog.000050(包括)之后的的binlog文件就行了
image.png

  1. cp /var/lib/mysql/binlog.000050 /backup/
  2. cp /var/lib/mysql/binlog.000051 /backup/

image.png
增量备份就到此结束了

2.1.4.1-基于xtrabackup的增量备份

目前xtrabackup还不支持mysql8.0这个地方后面要搞个mysql5.7的补

2.3-恢复(recovery)

2.3.1-数据磁损坏(一锤子把磁盘锤坏)

要想在磁盘损坏的情况下恢复数据,前提就是:

  1. 备份的文件和数据库文件(var/lib/mysql)不在一起,我们假设分开磁盘放。
  2. binlog日志文件和数据库文件也要单独分开,我们假设分开磁盘放。

image.png
现在这一行是注释掉的,所以binlog相关的都是直接放在数据目录下:/var/lib/mysql
image.png
我们修改二进制文件位置,并且重启服务
image.png

  1. service mysql restart

image.png
image.png

重新更换二进制文件目录,原来数据的二进制文件在原来的地方,这里是重新生成的。也就是说如果你应该从项目开始就这么做不要半途做,不然你都不晓得备份还原的节点是旧的二进制还是新的。

我们假设从这一刻开始是我们第一次使用数据库,我先创建一个新的db插入1百万条数据

  1. create database xiongyao charset=utf8mb4; //utf8mb4编码只是表情包是真正的utf8
  2. CREATE TABLE `order` (
  3. `id` BIGINT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT,
  4. `user_id` INT ( 32 ) DEFAULT 0 COMMENT '下单用户id',
  5. `order_id` VARCHAR ( 64 ) DEFAULT NULL COMMENT '订单号',
  6. `status` TINYINT ( 1 ) DEFAULT 1 COMMENT '该笔交易的状态0进行中;1支付完成;2支付失败;3取消支付;',
  7. `pay_type` TINYINT ( 1 ) DEFAULT 1 COMMENT '1支付宝2微信3银行卡',
  8. `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  9. `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  10. PRIMARY KEY ( `id` )
  11. ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
  1. import os
  2. import sys
  3. import random
  4. import pymysql.cursors
  5. import uuid
  6. def handler():
  7. mysql_connect = pymysql.connect(
  8. host="",
  9. user="root",
  10. port=3306,
  11. password="",
  12. database="xiongyao",
  13. cursorclass=pymysql.cursors.DictCursor,
  14. )
  15. with mysql_connect.cursor() as mysql_cursor:
  16. # 每次插入10000条
  17. values = "('c02f8f06b6bc468892328ab97c212562',32120,1,2)"
  18. for i in range(10000):
  19. order_id = str(uuid.uuid4()).replace("-", "")
  20. user_id = random.randint(1, 100000)
  21. # 从数仓数据库查询数据
  22. values += f",('{order_id}',{user_id},1,2)"
  23. sql_string = f"INSERT INTO `order`(order_id,user_id,`status`,pay_type) VALUES {values};"
  24. # print(sql_string)
  25. mysql_cursor.execute(sql_string, args=())
  26. mysql_connect.commit()
  27. mysql_connect.close()
  28. if __name__ == "__main__":
  29. print(f"开始时间:{datetime.datetime.now()}")
  30. from multiprocessing import Pool
  31. workers = os.cpu_count() * 2 + 1
  32. p = Pool(workers)
  33. # 100个任务,每个任务同时插入1w条数据=1百万条数据
  34. for i in range(0, 100):
  35. p.apply_async(handler, args=())
  36. p.close()
  37. p.join()
  38. #开始时间:2022-07-07 23:36:44.011341
  39. #结束时间:2022-07-07 23:37:36.939952
  40. print(f"结束时间:{datetime.datetime.now()}")

image.png

假设我们数据库服务上线了,第一天晚上进行了正常的全备份:

  1. #物理全备份
  2. cp -a /var/lib/mysql /backup/mysql-backup-physics
  3. #逻辑全备份
  4. mysqldump -u root -p --all-databases --flush-logs --master-data=2 --single-transaction --routine --triggers > all-database.sql;

image.png
第二天白天产生100万条的业务数据:

  1. 用上面的python再生成100万条数据

image.png
第二天晚上进行的是增量备份:
先查看上次的mysqldump逻辑备份的时候备份到哪个binglog节点了
image.png
所以我们要保存000003和它之后的binlog文件

  1. cp /var/log/mysql/mysql-bin.000003 /backup

第三天白天上午业务发生了50万条数据:

  1. 用上面的python再生成50万条数据

image.png

记住此时一同250万条数据

突然此时物理磁盘被炸弹炸坏了。。。。。

  1. rm -rf /var/lib/mysql

/var/lib下面没有mysql这个目录了
image.png
再也连不上去了
image.png

但是实际情况是 我删除了数据目录但是还是能上去的,过一会才不能上去。

开始恢复操作。。。。。

  1. cp -a /backup/mysql-backup-physics /var/lib
  2. cd /var/lib
  3. mv mysql-backup-physics mysql

image.png
重启mysql

  1. service mysql restart

image.png
image.png
现在数据库是100万条数据,是对的,因为我们上次无力备份的时候就是一百万数据。
下面我们需要进行增量备份的还原,先把00003之后的二进制文件全部拉出来
image.png

  1. /var/log/mysql/mysql-bin.000004 /backup
  2. /var/log/mysql/mysql-bin.000005 /backup

image.png

开始还原000003 000004 000005的文件内容

  1. mysqlbinlog --start-position=157 mysql-bin.000003 > mysql-bin-000003-diff.sql
  1. mysqlbinlog mysql-bin.000004 > mysql-bin-000004.sql
  2. mysqlbinlog mysql-bin.000005 > mysql-bin-000005.sql

image.png
恢复:

  1. mysql -uroot -p < mysql-bin-000003-diff.sql
  2. mysql -uroot -p < mysql-bin-000004.sql
  3. mysql -uroot -p < mysql-bin-000005.sql

image.png
恢复完成

2.3.2-程序员删库跑路(drop database)

  1. drop database xiongyao;

image.png
开始恢复操作。。。

  1. cp /var/log/mysql/mysql-bin.000001 /backup
  2. cp /var/log/mysql/mysql-bin.000002 /backup

我们之前是进行的全备份到000003节点,所以我们缺少两个文件,要补齐。

  1. mysqlbinlog --database=xiongyao mysql-bin.000001 > xiongyao-000001.sql
  2. mysqlbinlog --database=xiongyao mysql-bin.000002 > xiongyao-000002.sql
  3. mysqlbinlog --database=xiongyao mysql-bin.000003 > xiongyao-000003.sql
  4. mysqlbinlog --database=xiongyao mysql-bin.000004 > xiongyao-000004.sql
  5. mysqlbinlog --database=xiongyao mysql-bin.000005 > xiongyao-000005.sql

image.png
还原

  1. mysql -uroot -p < xiongyao-000001.sql
  2. mysql -uroot -p < xiongyao-000002.sql
  3. mysql -uroot -p < xiongyao-000003.sql
  4. mysql -uroot -p < xiongyao-000004.sql
  5. mysql -uroot -p < xiongyao-000005.sql

过程中还遇到了max_allowed_packet过小导致sql执行失败的问题,我是修改配置文件重启服务后直成功的

image.png

image.png
image.png

2.3.3-程序员误操作

在实际的过程中误操作delete和update没有加条件导致操作失误的问题很常见,我自己也犯过错

  1. select * from `order` where user_id=1681 ;

操作前一共23条数据

  1. +---------+---------+----------------------------------+--------+----------+---------------------+---------------------+
  2. | id | user_id | order_id | status | pay_type | created_at | updated_at |
  3. +---------+---------+----------------------------------+--------+----------+---------------------+---------------------+
  4. | 920095 | 1681 | f5866774acea4bf9a7ecc8f8b7e1a11e | 1 | 2 | 2022-07-07 23:40:48 | 2022-07-07 23:40:48 |
  5. | 1019183 | 1681 | 600f6278dae448768847d74f516fa822 | 1 | 2 | 2022-07-07 23:40:52 | 2022-07-07 23:40:52 |
  6. | 1031722 | 1681 | 4d2939d6546349a68366909cf417dd7f | 1 | 2 | 2022-07-07 23:40:53 | 2022-07-07 23:40:53 |
  7. | 1219841 | 1681 | 63a06f3777d746c9b1fc1fc2da0d4b02 | 1 | 2 | 2022-07-07 23:41:02 | 2022-07-07 23:41:02 |
  8. | 1244914 | 1681 | ed346cd9ae064fd68eacdb354552ed69 | 1 | 2 | 2022-07-07 23:41:06 | 2022-07-07 23:41:06 |
  9. | 1271526 | 1681 | 2150ff9debe14e518eeeb3f58d3530bf | 1 | 2 | 2022-07-07 23:41:06 | 2022-07-07 23:41:06 |
  10. | 1396173 | 1681 | a1c53ca3ac91416baf21e95405abaa2f | 1 | 2 | 2022-07-07 23:41:14 | 2022-07-07 23:41:14 |
  11. | 1485125 | 1681 | 7212c2c12da746e984c9a75cb966b940 | 1 | 2 | 2022-07-07 23:41:19 | 2022-07-07 23:41:19 |
  12. | 1571910 | 1681 | a2173eaa135548a2be919921f9b02435 | 1 | 2 | 2022-07-07 23:41:24 | 2022-07-07 23:41:24 |
  13. | 1787781 | 1681 | 27c577c4d3784d9b8689f6900b736c14 | 1 | 2 | 2022-07-07 23:41:34 | 2022-07-07 23:41:34 |
  14. | 1789536 | 1681 | b2f86a0e837a47dc828c5c443f52adda | 1 | 2 | 2022-07-07 23:41:34 | 2022-07-07 23:41:34 |
  15. | 2141209 | 1681 | 226d3b1ef3cf49b5bfb9d7126b63174b | 1 | 2 | 2022-07-07 23:51:03 | 2022-07-07 23:51:03 |
  16. | 2348930 | 1681 | 753d6a6f27c446dd9fd4cb9ea6d2cb5e | 1 | 2 | 2022-07-07 23:51:11 | 2022-07-07 23:51:11 |
  17. | 2533803 | 1681 | 57e14299d42e4c10aa10e870f3d152e8 | 1 | 2 | 2022-07-07 23:51:23 | 2022-07-07 23:51:23 |
  18. | 2550198 | 1681 | 4887287156494cc7967e614f060e8323 | 1 | 2 | 2022-07-07 23:51:24 | 2022-07-07 23:51:24 |
  19. | 2569084 | 1681 | b724008b97204b408f9d4217cdd42b9a | 1 | 2 | 2022-07-07 23:51:24 | 2022-07-07 23:51:24 |
  20. | 2571130 | 1681 | 24f5c935ffc74eee8c9691786ea0b8cf | 1 | 2 | 2022-07-07 23:51:24 | 2022-07-07 23:51:24 |
  21. | 2870748 | 1681 | 3c86abe555e3474eb52665c9503904e3 | 1 | 2 | 2022-07-07 23:51:37 | 2022-07-07 23:51:37 |
  22. | 3018927 | 1681 | b0b873d4a46a4cfeb12bad08de42ec25 | 1 | 2 | 2022-07-07 23:58:29 | 2022-07-07 23:58:29 |
  23. | 3105966 | 1681 | 1f6337a231bf47269b29eb115078705e | 1 | 2 | 2022-07-07 23:58:34 | 2022-07-07 23:58:34 |
  24. | 3232810 | 1681 | ffac16b7b84a44a4985b74bedc9281f2 | 1 | 2 | 2022-07-07 23:58:39 | 2022-07-07 23:58:39 |
  25. | 3293738 | 1681 | ad3062050d9b49ed9d12d5b2bb86f1a6 | 1 | 2 | 2022-07-07 23:58:42 | 2022-07-07 23:58:42 |
  26. | 3394882 | 1681 | e338b53362f64714bdd5830f51624b32 | 1 | 2 | 2022-07-07 23:58:45 | 2022-07-07 23:58:45 |
  27. +---------+---------+----------------------------------+--------+----------+---------------------+---------------------+

误操作:

  1. update `order` set order_id = "000000000001" where user_id = 1681;

本来我只是想update user_id=1681和order_id=e338b53362f64714bdd5830f51624b32的数据的,但是我少了一个order_id=e338b53362f64714bdd5830f51624b32条件

image.png
image.png
开始恢复

  1. show master status;

image.png

  1. mysqlbinlog --start-datetime='2022-07-08 01:00:00' --stop-datetime='2022-07-08 02:00:00' --database=xiongyao /var/log/mysql/mysql-bin.000010 -v


order_update.sql
image.png
找到原始sql怎么还原都可以。