华子目录
MySQL日志管理
为什么需要日志
- 用于
排错
- 用来做
数据分析
- 了解
程序
的运行情况
,了解MySQL
的性能
日志作用
- 在
数据库
保存数据
时,有时候不可避免
会出现数据丢失
或者被破坏
,这样情况下,就必须保证数据
的安全性
和完整性
,则需要使用日志
来查看
或者恢复数据
日志文件查看方法
- 由于
多种
安装mysql
的方法
可能导致文件存储位置
和名称不同
,需要先通过mysql配置文件
确定错误日志文件位置
及名称
bash
[root@mysql ~]# cat /etc/my.cnf
log-error=/var/log/mysqld.log #错误日志
- 查看
mysql数据目录
中的日志文件
bash
[root@mysql ~]# cat /etc/my.cnf
datadir=/var/lib/mysql
错误日志
错误日志
记录以下信息:
服务器启动
和关闭过程
中的信息
服务器运行过程
中的错误信息
事件调度器
运行一个时间
是产生的信息
- 在
从服务器
上启动从服务器
进程是产生的信息
sql
#查看错误日志位置及文件名,一般以主机名.err方式命名
mysql> show variables like "log_error";
+---------------+---------------------+
| Variable_name | Value |
+---------------+---------------------+
| log_error | /var/log/mysqld.log | #错误日志文件在主机中的存储位置
+---------------+---------------------+
错误日志
信息需要注意三类
:[System]
、[Warning]
、[Error]
-
[System]
:- 描述 :
[System]
级别的日志条目通常记录
的是系统级
的信息
,比如MySQL服务
的启动
和停止时间
、配置文件
读取情况、系统变量
设置等。 - 用途 :这些信息对于理解
数据库服务器
的启动过程、配置文件的加载
以及系统变量的最终设置状态
非常有用。
- 描述 :
-
[Warning]
:- 描述 :
[Warning]
级别的日志条目记录
的是警告信息
,这些信息表明数据库操作
中存在潜在的问题
或不符合预期
的行为
,但这些问题通常不会
导致数据库
立即停止工作
或数据丢失
。 - 用途 :
警告信息
可以帮助数据库管理员
(DBA
)识别
和解决可能的问题源
,从而避免未来可能出现的更严重问题。
- 描述 :
-
[Error]
:- 描述 :
[Error]
级别的日志条目记录
的是错误信息
,这些信息表明数据库
操作中遇到了严重问题
,可能会导致数据库功能受限
、性能下降
或数据损坏
。 - 用途 :
错误信息
对于快速定位
和解决问题
至关重要。DBA
应该立即关注这些条目
,并根据错误信息
进行故障排除
和修复
- 描述 :
通用查询日志
- 由于
数据库
一般有多条连接
,不一定
是本地连接
,所以需要记录每个连接客户端
的所有操作
,包括启动
和关闭MySQL服务
、更新语句
和查询语句
等,从而产生查询日志
- 查看
设置状态
sql
mysql> show global variables like "%general_log%";
+------------------+--------------------------+
| Variable_name | Value |
+------------------+--------------------------+
| general_log | OFF | #默认关闭
| general_log_file | /var/lib/mysql/mysql.log | #通用日志文件存储位置
+------------------+--------------------------+
- 启动
通用查询日志
bash
mysql> set global general_log=1;
mysql> show global variables like "%general_log%";
+------------------+--------------------------+
| Variable_name | Value |
+------------------+--------------------------+
| general_log | ON |
| general_log_file | /var/lib/mysql/mysql.log |
+------------------+--------------------------+
# 注意这是临时更改,若永久更改则在my.cnf中配置general-log=1,并重启服务
# 注意可以在my.cnf中设置 general_log_file=路径/文件名 的形式设置永久更改存储位置
- 设置日志记录
类型
(表
/文本文件
/空
)
bash
mysql> show variables like "%log_output%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | FILE |
+---------------+-------+
#注意可以在my.cnf中设置log-output={TABLE|FILE|NONE}类型
注意
:
- 要启用
通用查询日志
,需要至少配置general-log=1
,log-output={TABLE|FILE}
general_log_file
如果没有指定
,默认名
是:主机名.log
默认通用查询日志
是不开启的
,因为会消耗
大量的磁盘空间
、CPU
以及内存
,所以当需要通过查询日志
还原操作场景
准确定位问题
时可以短时间开启
bash
# 可以通过下面的查询测试查询日志的文件变化
mysql> show variables like "%general_log%";
+------------------+--------------------------+
| Variable_name | Value |
+------------------+--------------------------+
| general_log | ON |
| general_log_file | /var/lib/mysql/mysql.log |
+------------------+--------------------------+
mysql> use view;
mysql> show tables;
+----------------+
| Tables_in_view |
+----------------+
| class |
| student |
| viewInfo_stu |
| view_stu |
| view_stu1 |
+----------------+
mysql> select * from student;
+----+-------+-----+--------+--------------------+---------+
| id | name | age | gender | address | classid |
+----+-------+-----+--------+--------------------+---------+
| 1 | 文 | 21 | M | 陕西省西安市 | 1003 |
| 2 | rong | 18 | F | 陕西省榆林市 | 1001 |
| 3 | yuan | 19 | M | 陕西省西安市 | 1002 |
| 5 | hua | 10 | M | 山西省 | 1001 |
| 6 | huazi | 9 | M | 山西省 | 1002 |
+----+-------+-----+--------+--------------------+---------+
bash
[root@mysql ~]# cat /var/lib/mysql/mysql.log
/usr/sbin/mysqld, Version: 8.4.3 (MySQL Community Server - GPL). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
2024-11-30T07:52:20.060357Z 15 Init DB view
2024-11-30T07:52:20.061025Z 15 Query show databases
2024-11-30T07:52:20.061583Z 15 Query show tables
2024-11-30T07:52:20.062232Z 15 Query SELECT * FROM `class` LIMIT 0
2024-11-30T07:52:20.063133Z 15 Query SELECT * FROM `student` LIMIT 0
2024-11-30T07:52:20.063937Z 15 Query SELECT * FROM `viewInfo_stu` LIMIT 0
2024-11-30T07:52:20.064518Z 15 Query SELECT * FROM `view_stu` LIMIT 0
2024-11-30T07:52:20.064896Z 15 Query SELECT * FROM `view_stu1` LIMIT 0
2024-11-30T07:52:29.367548Z 15 Query show tables
2024-11-30T07:52:43.639933Z 15 Query select * from student
- 关闭通用查询日志
sql
mysql> set global general_log=0;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like "%general_log%";
+------------------+--------------------------+
| Variable_name | Value |
+------------------+--------------------------+
| general_log | OFF |
| general_log_file | /var/lib/mysql/mysql.log |
+------------------+--------------------------+
慢查询日志
慢日志记录
所有执行时间
超过long_query_time秒
的所有查询
或不使用索引
的查询
解释
:若某条查询语句
的执行时间过长
,超过
了设定的阈值
则就会记录
到慢日志
中,可以对其进行后期select语句
的优化
- 查看
慢查询日志
状态
sql
mysql> show variables like "%slow_query_log%";
+---------------------+-------------------------------+
| Variable_name | Value |
+---------------------+-------------------------------+
| slow_query_log | ON | #开启状态
| slow_query_log_file | /var/lib/mysql/mysql-slow.log | #日志文件位置
+---------------------+-------------------------------+
- 开启
慢查询日志
sql
mysql> set global slow_query_log=1;
# 注意:为了服务器调优,建议开启
慢日志
的时间阈值
sql
mysql> show variables like "%long_query_time%";
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 10.00000 | #默认为10秒,精度可以到微秒
+-----------------+----------+
撤销日志
Undo-log日志
:即撤销日志
或回滚日志
,Undo
即撤销
的意思,在日常开发过程
中,如果代码敲错
了,一般会习惯性
的按下Ctrl+Z
撤销,而Undo-log
的作用也是如此
,但它是用来给MySQL
撤销SQL
操作的。Undo-log日志
记录内容:- 若是
insert
插入操作,则生成一个对应的delete
操作。 - 若是
delete
删除操作,InnoDB
中会修改隐藏字段deleted_bit=1
,则生成改为0
的语句。 - 若是
update
修改操作,如:将性别
从男
改成了女
,则就生成
一个从女
改回男
的操作
- 若是
- 可以理解为:当一条
写入类型
的SQL
执行时,都会在Undo-log
日志中生成相应
的反SQL
放入到Undo-log
中
bash
#从mysql8.0.20版本开始存储位置
[root@mysql ~]# cd /var/lib/mysql/
[root@mysql mysql]# ls #以undo开头的文件是撤销日志
undo_001
undo_002
重做日志
InnoDB引擎
在设计时
是基于磁盘
存储数据的
,当MySQL
启动后就会在内存
中创建一个BufferPool
,运行过程
中会将大量操作
汇集在内存
中进行
,比如写入数据
时,先写到内存
中,然后由后台线程
再刷写
到磁盘
- 虽然使用
BufferPool
提升了MySQL
整体的读写性能
,但它是基于内存
的,也就意味着随着机器
的宕机
、重启
,其中保存的数据
会消失
,当向内存
中写入数据
后,MySQL
突然宕机
了,则这条未刷写
到磁盘
的数据
会丢失
,也正由于该原因
,redo-log
应运而生 redo-log
:重做日志
,是一种预写式日志
,即在向内存
写入数据
前,会先写日志
,当后续数据
未被刷写
到磁盘
、MySQL崩溃
时,就可以通过日志
来恢复数据
,确保所有提交
的事务
都会被持久化
mysql8
中Redo-log
存储在/var/lib/mysql/#innodb_redo
目录下,由32
个文件
组成有两种类型
的redo log文件
,一种是当前正在使用
的#ib_redoN
;另一种是空闲的文件名
为#ib_redoN_tmp
,多加了个_tmp
后缀
sql
mysql> select * from performance_schema.innodb_redo_log_files\G;
*************************** 1. row ***************************
FILE_ID: 148
FILE_NAME: ./#innodb_redo/#ib_redo148
START_LSN: 484671488
END_LSN: 487946240
SIZE_IN_BYTES: 3276800
IS_FULL: 0
CONSUMER_LEVEL: 0
sql
mysql> show status like "%innodb%redo%";
+-------------------------------------+-----------+
| Variable_name | Value |
+-------------------------------------+-----------+
| Innodb_redo_log_read_only | OFF |
| Innodb_redo_log_uuid | 952782583 |
| Innodb_redo_log_checkpoint_lsn | 486687544 |
| Innodb_redo_log_current_lsn | 486687544 |
| Innodb_redo_log_flushed_to_disk_lsn | 486687544 |
| Innodb_redo_log_logical_size | 512 |
| Innodb_redo_log_physical_size | 3276800 |
| Innodb_redo_log_capacity_resized | 104857600 |
| Innodb_redo_log_resize_status | OK |
| Innodb_redo_log_enabled | ON |
+-------------------------------------+-----------+
二进制日志
---重要
二进制日志
作用:
- 记录
所有更改数据
的语句
(insert、update、delete等
),不记录
查询语句 - 用于
主从复制
,因为从服务器
需要到主服务器
里拷贝二进制日志
,然后根据二进制日志
的内容
去执行SQL语句
,从而达到主从服务器
里的数据一模一样
- 用于
恢复数据
日志审计
的场景
:用户
可以通过二进制日志
中的信息
来进行审计
,判断
是否有对数据库
进行注入攻击
(mysql
注入攻击
:黑客
可以提交一段数据库查询代码
,根据程序返回的结果
,获得
某些想要得到的数据
)
sql
[root@mysql ~]# cd /var/lib/mysql/
[root@mysql mysql]# ls
binlog.000001
binlog.000002
binlog.000003
binlog.000004
binlog.000005
binlog.000006
binlog.000007
binlog.000008
binlog.000009
- 查看
二进制日志状态
sql
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 |
| sql_log_bin | ON |
+---------------------------------+-----------------------------+
- 日志查看
sql
#查看有哪些二进制日志文件
mysql> show binary logs;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 26826 | No |
| binlog.000002 | 181 | No |
| binlog.000003 | 158 | No |
| binlog.000004 | 158 | No |
| binlog.000005 | 83200151 | No |
| binlog.000006 | 12162 | No |
| binlog.000007 | 181 | No |
| binlog.000008 | 2753 | No |
| binlog.000009 | 2651 | No |
+---------------+-----------+-----------+
#显示名称、容量单位字节、加密与否
sql
# 查看当前正在使用的是哪一个二进制日志文件
mysql> show master status;
sql
#查看二进制日志内容
mysql> show binlog events in "binlog.000001";
- 使用命令
mysqlbinlog
查看二进制日志内容
sql
# 使用命令mysqlbinlog查看二进制日志内容
[root@mysql ~]# cd /var/lib/mysql/
[root@mysql mysql]# mysqlbinlog binlog.000001
分割日志
:新的操作
会记录的新的日志文件
中- 使用
mysqladmin
刷新日志
- 使用
bash
#每刷新一次,就会产生一个binlog日志
[root@mysql ~]# mysqladmin flush-logs -uroot -p
Enter password:
[root@mysql ~]# mysql -uroot -p
#新建数据库
mysql> create database mydb12_journal;
mysql> show master status;
mysql> show binary logs;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 26826 | No |
| binlog.000002 | 181 | No |
| binlog.000003 | 158 | No |
| binlog.000004 | 158 | No |
| binlog.000005 | 83200151 | No |
| binlog.000006 | 12162 | No |
| binlog.000007 | 181 | No |
| binlog.000008 | 2753 | No |
| binlog.000009 | 2695 | No |
| binlog.000010 | 202 | No |
+---------------+-----------+-----------+
bash
[root@mysql mysql]# mysqlbinlog binlog.000010
......
create database mydb12_journal
......
日志刷新
作用
:通过刷新日志
进行更新日志
,对缓存数据
进行磁盘I/O
,并强制mysqld
来关闭
和重新
打开日志文件
(或者在某些情况下
切换到一个新的日志
)- 由于
日志
的记录
不是直接
写入磁盘上的日志文件
中而是使用日志缓存
的方式
,当频繁
执行多条修改
的sql语句
时,为了避免
对磁盘频繁I/O
,会将日志记录
写入到内存
的特殊空间
即日志缓存
中,之后每隔一个固定时间间隔
将缓存的日志
写入到磁盘文件
中
刷新日志命令
格式
sql
#每刷新一次,就会产生一个binlog文件
mysql> flush logs;
mysql> show master status;
bash
#在shell中,通过mysqladmin命令执行日志刷新
[root@mysql ~]# mysqladmin flush-logs -uroot -p
Enter password:
#或,但是refresh会重置binlog文件,将之前的binlog文件全部删除,再新建一个binlog.00001文件
[root@mysql ~]# mysqladmin refresh -uroot -p
Enter password:
不小心删库后应该跑路吗?
- 如果
在线上
真的删库
了,哪就先别想着跑路
,你跑不掉!
bin-log日志
中会记录执行SQL
的连接会话信息
,同时一般规模较大的企业
,都会搭建
完善的监控系统
,会监控服务
的网络连接
- 因此当你
删库
后,他们可以顺着bin-log → session → network-connection
这条线确定执行
删库SQL
的IP
!如果你还未断开连接
,直接通过MySQL
的命令
就能定位到删库
的IP
,因此基本上删库
了,是可以定位
到责任人的
- 因此当你
删库
后,可以直接
去本地
找Bin-log
的日志文件
,然后拷贝出来一份
,再打开最后一个文件
,把里面删库
的记录
手动移除
,再利用mysqlbinlog
工具导出xx.SQL
文件,最后执行该SQL
文件即可恢复删库前
的数据
中继日志
-
Relay-log
:中继日志
,在单库
中是见不到的
,该类型
的日志
仅存在主从架构
中的从机
上 -
主从架构
中的从机
,其数据
基本上都是复制
主机bin-log日志
同步过来
并放在relay-log日志
中,中继日志
的作用
就跟它的名字
一样,仅仅只是作为主从同步
数据的"中转站
"
MySQL备份
备份类型
- 根据
服务器状态
,可以分为热备份
、温备份
、冷备份
热备份
:读、写不受影响
温备份
:仅
可以执行读操作
冷备份
:离线备份
;读、写操作均中止
- 从
对象
来分,可以分为物理备份
与逻辑备份
物理备份
:复制数据文件
逻辑备份
:将数据
导出至文本文件
中
- 从
数据收集
来分,可以完全备份
、增量备份
、差异备份
完全备份
:备份全部数据
增量备份
:仅备份
上次完全备份
或增量备份
以后变化的数据
差异备份
:仅备份
上次完全备份
以来变化的数据
逻辑备份优缺点
- 在
备份速度
上两种备份
要取决于不同的存储引擎
物理备份
的还原速度
非常快
。但是物理备份
的最小粒度
只能做到表
逻辑备份
保存的结构
通常都是纯ASCII
的,所以我们可以使用文本处理工具
来处理
逻辑备份
有非常强
的兼容性
,而物理备份
则对版本要求
非常高
逻辑备份
也对保持数据
的安全性
有保证
逻辑备份
的缺点
:逻辑备份
要对RDBMS
产生额外的压力
,而裸备份无压力
逻辑备份
的结果
可能要比源文件更大
。所以很多人都对备份
的内容
进行压缩
逻辑备份
可能会丢失浮点数
的精度信息
备份内容
数据文件
日志文件
(比如事务日志
,二进制日志
)存储过程
,存储函数
,触发器
配置文件
(十分重要
,各个配置文件
都要备份
)- 用于
实现数据库备份
的脚本
,数据库自身清理
的Crontab
等......
备份工具
MySQL
自带的备份工具
--mysqldump
,是mysql
数据库管理系统自带
的逻辑备份
工具,支持完全备份
+增加备份
,速度相对较慢
,适合中小型数据库
,支持所有引擎
,备份策略
:第一次完全备份
,每天
一次增量备份
,每周
再做一次完全备份
,如此一直重复
完全备份语法
bash
[root@mysql ~]# mysqldump -u用户名 --password=密码 -A > 绝对路径\备份文件.sql
备份库
语法
sql
[root@mysql ~]# mysqldump -u用户名 --password=密码 -B 数据库名1 数据库名2 > 绝对路径\备份文件.sql
备份库中表
语法
sql
[root@mysql ~]# mysqldump -u用户名 --password=密码 数据库名 表1 表2 > 绝对路径\备份文件.sql
- 示例1:使用
mysqldump
工具实现全量备份
sql
# 原理:必须先做全量备份,使得数据库有一个基准还原点,在做增量备份,还原差异数据
[root@mysql ~]# mysqldump -uroot --password=123456 -A > back1.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
#警告表示将密码显示在屏幕上不安全,备份的盘符一定要和MySQL安装目录在同一个盘符中,要不然会提示:拒绝访问
# 进入mysql中,删库
[root@mysql ~]# mysql -uroot -p
Enter password:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| events |
| huazi |
| information_schema |
| mydb12_journal |
| mydb13_indexdb |
| mydb17_transcation |
| mysql |
| performance_schema |
| sys |
| view |
+--------------------+
mysql> drop database events;
mysql> drop database huazi;
......
mysql> drop database view;
mysql> show databases;
+--------------------+
| Database | #这3个库,root用户删不了
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
mysql> quit
Bye
[root@mysql ~]# mysql -uroot -p
Enter password:
#全库恢复
mysql> source /root/back1.sql
#发现没有对sys库做备份
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| events |
| huazi |
| information_schema |
| mydb12_journal |
| mydb13_indexdb |
| mydb17_transcation |
| mysql |
| performance_schema |
| view |
+--------------------+
mysql> use view;
mysql> show tables;
+----------------+
| Tables_in_view |
+----------------+
| class |
| student |
| viewInfo_stu |
| view_stu |
| view_stu1 |
+----------------+
mysql> select * from student;
+----+-------+-----+--------+--------------------+---------+
| id | name | age | gender | address | classid |
+----+-------+-----+--------+--------------------+---------+
| 1 | 文 | 21 | M | 陕西省西安市 | 1003 |
| 2 | rong | 18 | F | 陕西省榆林市 | 1001 |
| 3 | yuan | 19 | M | 陕西省西安市 | 1002 |
| 5 | hua | 10 | M | 山西省 | 1001 |
| 6 | huazi | 9 | M | 山西省 | 1002 |
+----+-------+-----+--------+--------------------+---------+
- 示例2:
局部备份恢复
sql
#对view库做备份
[root@mysql ~]# mysqldump -uroot --password=123456 -B view > back2.sql
[root@mysql ~]# mysql -uroot -p
Enter password:
#删除view库
mysql> drop database view;
#开始恢复
mysql> source /root/back2.sql
#发现已经恢复
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| events |
| huazi |
| information_schema |
| mydb12_journal |
| mydb13_indexdb |
| mydb17_transcation |
| mysql |
| performance_schema |
| view |
+--------------------+
mysql> use view;
mysql> show tables;
+----------------+
| Tables_in_view |
+----------------+
| class |
| student |
| viewInfo_stu |
| view_stu |
| view_stu1 |
+----------------+
mysql> select * from student;
+----+-------+-----+--------+--------------------+---------+
| id | name | age | gender | address | classid |
+----+-------+-----+--------+--------------------+---------+
| 1 | 文 | 21 | M | 陕西省西安市 | 1003 |
| 2 | rong | 18 | F | 陕西省榆林市 | 1001 |
| 3 | yuan | 19 | M | 陕西省西安市 | 1002 |
| 5 | hua | 10 | M | 山西省 | 1001 |
| 6 | huazi | 9 | M | 山西省 | 1002 |
+----+-------+-----+--------+--------------------+---------+
文件系统
备份工具cp命令
,冷备份
,支持所有引擎
,复制命令
,只能
实现冷备
,物理备份
。使用归档工具
,cp命令
,对其进行备份时,备份速度快
,还原速度
几乎最快
,但是灵活度很低
,可以跨系统
,但是跨平台
能力很差
lvm
几乎是热备份
,支持所有引擎
,基于快照
(LVM
,ZFS
)的物理备份
,速度非常快
,几乎
是热备
。只影响数据几秒钟
而已。但是创建快照
的过程
本身就影响到了数据库在线
的使用
,所以备份速度
比较快
,恢复速度
比较快
,没有什么弹性空间
,而且LVM
的限制
:不能
对多个逻辑卷
同一时间
进行备份
,所以数据文件
和事务日志
等各种文件
必须放在同一个LVM
上。而ZFS
则非常好
的可以在多逻辑卷之间
备份
其它工具
ibbackup
商业工具MyISAM
是温备份
,InnoDB
是热备份
,备份
和还原
速度都很快
,这个软件
它的服务器授权版本
是5000美元
xtrabackup
开源工具MyISAM
是温备份
,InnoDB
是热备份
,是ibbackup
商业工具
的替代工具
mysqlbackup ORACLE
公司也提供了针对企业
的备份
软件MySQL Enterprise Backup
简称:mysqlbackup