欢迎来到十九分快乐的博客

生死看淡,不服就干。

9. MySQL - 搜索引擎 - 日志

一.搜索引擎

参考网址: https://www.cnblogs.com/Neeo/articles/13883976.html#锁

InnoDB主要功能

多版本并发控制(MVCC)

事务

行级锁

外键

备份(热备)和恢复

自动故障恢复(ACSR)
....

InnoDB存储引擎逻辑存储结构

在InnoDB存储引擎中,所有数据都存放在表空间(tablespace)中,表空间由段(segment)、区(extent)、页(page)、行(Row)组成

buffer pool 缓冲池

事务

隔离级别

RR:RR级别解决了脏读问题并和MVCC一起解决"幻读"问题,该级别保证了在同一个事物中多次读取同样记录的结果是一致的。

该级别是MySQL的默认事务隔离级别。

RC:大多数数据库系统的默认隔离级别都是RC(但MySQL不是!),RC满足前面提到的隔离性的简单定义:一个事务开始时,只能"看见"已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读(nonrepeatable read),因为两次执行同样的查询,可能会得到不一样的结果。

RR与RC测试:

-- 支持 session 和 global 级别设置
set transaction_isolation='READ-UNCOMMITTED';
set transaction_isolation='READ-COMMITTED';
set transaction_isolation='REPEATABLE-READ';
set transaction_isolation='SERIALIZABLE';

-- 也支持配置文件设置 vim /etc/my.cnf
[mysqld]
transaction_isolation=READ-COMMITTED

-- 设置自动提交
set autocommit=0;
select @@autocommit; -- 查看是否自动提交
select @@tx_isolation; -- 查看隔离级别

二.日志

1.错误日志 - error log

-- MySQL默认将错误日志输出到控制台,而不是文件中stderr
-- 查看错误日志输出到哪里,如果是stderr,说明没有配置错误日志
select @@log_error;
+---------------------------------+
| @@log_error                     |
+---------------------------------+
| /data/mysql/3306/logs/mysql.log |
+---------------------------------+

作用:

错误日志的作用就是记录启动、日常运行、关闭过程中,MySQL的相关状态信息、警告信息、错误信息。

配置:

我们也可以通过在配置文件(/etc/my.cnf)中配置

  • log_error:错误日志位置。
  • log_error_verbosity,MySQL5.7.20版本更高版本中,用来替代log_warnings参数,用来控制服务器将错误,警告和注释消息写入错误日志的详细程度,默认值为3:

log_error_verbosity=1,将Error messages输入到文件。

log_error_verbosity=2,将Error and warning messages输入到文件。

log_error_verbosity=3,将Error, warning, and information messages输入到文件。

来配置一下,然后重启MySQL服务生效:

[root@cs ~]# vim /etc/my.cnf 

[mysqld]
log_error=/data/mysql/3306/logs/mysql_error.log
# log_error_verbosity=3

[root@cs ~]# systemctl restart mysqld

flush logs 命令用来动态的刷新错误日志文件

比如失手删除了错误日志,那么可以在不停机的情况下,来刷新日志,即该命令会检查错误日志是否存在,不存在则创建,如果文件存在则不会重新创建:

[root@cs ~]# rm -rf /data/mysql/3306/logs/mysql_error.log
[root@cs ~]# mysqladmin -uroot -p123 flush-logs		# 通过这个命令刷新log日志
[root@cs ~]# ls /data/mysql/3306/logs/

2.慢日志 - slow log

慢日志(Slow Log),也称慢查询日志。主要记录低效的SQL语句,便于我们后续对这些低效的SQL进行针对性的优化,以提高MySQL的性能。

开启慢日志

# 默认该功能是关闭的
mysql> select @@slow_query_log;
+------------------+
| @@slow_query_log |
+------------------+
|                0 |
+------------------+

# 开启慢日志,vim /etc/my.cnf,然后重启MySQL:
[mysqld]
slow_query_log=1
slow_query_log_file=/data/mysql/3306/logs/slow.log
long_query_time=0.2
log_queries_not_using_indexes=1
  • slow_query_log:默认为0表示关闭,设置为1表示开启慢日志记录功能。
  • slow_query_log_file:慢日志记录的存储位置。当然,它默认存储在你MySQL的数据目录内,名叫主机名-slow.log。但我们一般都是日志和数据分离,所以都选择自定义日志位置。
  • 符合以下条件的才记录到慢日志中:
    • long_query_time:查询语句查询时间超过long_query_time时,默认是10秒。这个参数需要根据实际的应用场景来设置。
    • log_queries_not_using_indexes:查询语句没走索引时,1表示开启该功能。当然,你也可以直接将这个参数填写到配置文件中,而不用赋值,也可以的。

随便写一些查询语句,让慢语句被记录:

[root@cs ~]# cat /data/mysql/3306/logs/slow.log | head -n 1

# Time: 2021-05-13T10:34:41.712516Z
# User@Host: root[root] @ localhost []  Id:     3
# Query_time: 1.576822  Lock_time: 0.000166 Rows_sent: 1000000  Rows_examined: 1000000
use db1;
SET timestamp=1620902081;
select * from idb.pressure;

慢日志中主要记录了:

  • 这条语句的执行时间。
  • 这条语句的内容。
  • 执行这条语句的客户端。
  • 语句的查询时间。
  • 锁定时间。
  • 返回了多少行。

3.二进制日志 - bin log

二进制日志(Bin Log),也称之为复制日志(Replication Log),是MySQL中最重要的日志,它的主要作用是:

  • 备份恢复必须依赖二进制日志
  • 主从环境必须依赖二进制日志

开启二进制日志:

bin log默认是关闭的。

select @@sql_log_bin;
+---------------+
| @@sql_log_bin |
+---------------+
|             0 |
+---------------+

想要开启bin log,首先要创建一个存储路径binlog:

[root@cs ~]# mkdir /data/mysql/3306/logs/binlog
[root@cs ~]# chown -R mysql:mysql /data/mysql/3306/logs/binlog

# 修改配置文件
[root@cs ~]# vim /etc/my.cnf
[mysqld]
# mysql-bin 日志名前缀
log_bin=/data/mysql/3306/logs/binlog/mysql-bin
binlog_format=row

# 重启服务
[root@cs ~]# systemctl restart mysqld
[root@cs ~]# ll /data/mysql/3306/logs/binlog/

event 事件

什么是事件(event)?

事件是binlog的最小记录单元。

对于DDL、DCL,一个语句就是一个事件。

对于DML语句来说,一个(已提交的)事务就是一个事件

事件的作用

用于binlog的截取、分析、恢复。

一个事件有三部分组成:

  • 事件的开始位置,在binlog中用pos标识(position)。注意,一个事件的开始其实也是上一个事件的结束位置。
  • 事件的内容。
  • 事件的结束,在binlog中用end_log_pos标识,注意,一个事件的结束其实也是下一个事件的开始位置。

那在什么情况下MySQL会自动的拆分binlog呢?

  • 手动flush logs;时,该命令可以重复运行。
  • MySQL服务重启后。

查看

show binary logs; -- 返回log_basename下所有的binlog文件
flush logs;	-- 手动刷新log,MySQL会自动创建一个新的bin log文件
show master status;	-- 查询MySQL正在使用的bin log文件
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |     1139 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

-- 然后使用show binlog events in 'bin log文件名'来查看文件内容
show binlog events in 'mysql-bin.000001';
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 |   4 | Format_desc    |         6 |         123 | Server ver: 5.7.20-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids |         6 |         154 |                                       |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+

bin log文件的position从4开始到154,都是算是头信息

4.数据恢复

根据position号恢复数据,忽略GTID

1. 进行一些操作,误删库,恢复数据

 create database db2 charset utf8;
 use db2
 create table t1(id int);
 insert into t1 values(1),(2);
 drop database db2;

**2. 截取日志 从二进制日志文件定位到上一步操作position 起始号 结束号 **

-- 1.确认当前使用的binlog日志
show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154      |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

-- 2.查看当前使用的binlog日志
show binlog events in 'mysql-bin.000001';
+------------------+------+----------------+-----------+-------------+---------------------------------------+
| Log_name         | Pos  | Event_type     | Server_id | End_log_pos | Info                                  |
+------------------+------+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 | 4    | Format_desc    | 6         | 123         | Server ver: 5.7.20-log, Binlog ver: 4 |
| mysql-bin.000001 | 123  | Previous_gtids | 6         | 154         |                                       |
| mysql-bin.000001 | 154  | Anonymous_Gtid | 6         | 219         | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql-bin.000001 | 219  | Query          | 6         | 323         | create database db2 charset utf8      |
| mysql-bin.000001 | 323  | Anonymous_Gtid | 6         | 388         | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql-bin.000001 | 388  | Query          | 6         | 483         | use `db2`; create table t1(id int)    |
| mysql-bin.000001 | 483  | Anonymous_Gtid | 6         | 548         | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql-bin.000001 | 548  | Query          | 6         | 619         | BEGIN                                 |
| mysql-bin.000001 | 619  | Table_map      | 6         | 663         | table_id: 236 (db2.t1)                |
| mysql-bin.000001 | 663  | Write_rows     | 6         | 703         | table_id: 236 flags: STMT_END_F       |
| mysql-bin.000001 | 703  | Xid            | 6         | 734         | COMMIT /* xid=37 */                   |
| mysql-bin.000001 | 734  | Anonymous_Gtid | 6         | 799         | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql-bin.000001 | 799  | Query          | 6         | 870         | BEGIN                                 |
| mysql-bin.000001 | 870  | Table_map      | 6         | 914         | table_id: 236 (db2.t1)                |
| mysql-bin.000001 | 914  | Write_rows     | 6         | 954         | table_id: 236 flags: STMT_END_F       |
| mysql-bin.000001 | 954  | Xid            | 6         | 985         | COMMIT /* xid=38 */                   |
| mysql-bin.000001 | 985  | Anonymous_Gtid | 6         | 1050        | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql-bin.000001 | 1050 | Query          | 6         | 1139        | drop database db2                     |
+------------------+------+----------------+-----------+-------------+---------------------------------------+

-- 3.定位到position起始号219~结束号985

-- 4.根据position号截取日志 -- mysqlbinlog
-- 起始position号 - 结束position号 - 想要截取的日志文件 - 截取到哪个文件
[root@cs ~]# mysqlbinlog --start-position=219 --stop-position=985 /data/mysql/3306/logs/binlog/mysql-bin.000001 > /tmp/bin.sql
[root@cs ~]# ls /tmp/binlog*

3. 数据恢复

-- 关闭binlog日志服务
set sql_log_bin=0;
-- 数据恢复
source /tmp/bin.sql;
-- 恢复binlog日志服务
set sql_log_bin=1;

-- 查看恢复的数据
select * from db2.t1;

根据GTID恢复数据

什么是GTID?

​ GTID,全称是Global Transation ID(全局事务ID),它的特点是全局且唯一,也就是它为每个事务生成一个全局的唯一ID,多用于备份恢复中,

​ GTID的另一个特点是具有幂等性,简单来说,在开启GTID后,MySQL在根据bin log做数据恢复时,重复的GTID事务不会再执行了,多用于备份恢复中

开启GTID

# 编辑mysql配置文件 
[root@cs ~]# vim /etc/my.cnf

[mysqld]
gtid-mode=on		
enforce-gtid-consistency=true	-- 强制gtid的一致性

# 重启mysql服务
[root@cs ~]# systemctl restart mysqld

查看gtid

-- 由于MySQL服务重启,又生成了一个新的 binlog 文件
-- 查看当前使用日志文件
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

-- 操作数据
mysql> create database db3 charset=utf8;

-- 再次查看 - Executed_Gtid_Set 就是GTID
mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000002 |      323 |              |                  | 98ddc71a-b12d-11eb-b85f-000c29b6f740:1 |
+------------------+----------+--------------+------------------+----------------------------------------+


上面的GTID的我们用:分为两部分

  • 左半部分,是唯一的UUID,这个UUID是哪来的?这个UUID来自于MySQL初始化时或者MySQL重启时,得到的一个UUID,然后存储到了MySQL数据目录中的auto.cnf中,该UUID是当前MySQL实例的唯一的UUID,因为具有唯一性,所以GTID也用了它。
  • 至于右半部分,则表示说,自从开启GTID后,bin log中总共记录了多少个事务。而我们在开启GTID后,创建了数据操作,它算一个事务,所以,右半部分是1。注意,它记录的是完整的事务。

基于GTID的bin log数据恢复示例

1. 伪造事故,进行一些操作, 误删表和库

create database db4 charset utf8;
use db4
create table t1(id int);
insert into t1 values(1),(2),(3);
create table t2(id int);
create table t3(id int);
insert into t3 values(1),(2);
drop table t3;
insert into t2 values(1),(2);
drop database db4;

2. 确定备份需要的GTID事件号, 截取日志

-- 1.查看当前使用的binlog日志文件
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+------------------+----------+--------------+------------------+-------------------------------------------+
| mysql-bin.000002 |     2077 |              |                  | 98ddc71a-b12d-11eb-b85f-000c29b6f740:1-10 |
+------------------+----------+--------------+------------------+-------------------------------------------+

-- 2.查看日志文件
mysql> show binlog events in 'mysql-bin.000002';
+------------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name         | Pos  | Event_type     | Server_id | End_log_pos | Info                                                               |
+------------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| mysql-bin.000002 |    4 | Format_desc    |         6 |         123 | Server ver: 5.7.20-log, Binlog ver: 4                              |
| mysql-bin.000002 |  123 | Previous_gtids |         6 |         154 |                                                                    |
| mysql-bin.000002 |  154 | Gtid           |         6 |         219 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:1'  |
| mysql-bin.000002 |  219 | Query          |         6 |         323 | create database db3 charset=utf8                                   |
| mysql-bin.000002 |  323 | Gtid           |         6 |         388 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:2'  |
| mysql-bin.000002 |  388 | Query          |         6 |         492 | create database db4 charset utf8                                   |
| mysql-bin.000002 |  492 | Gtid           |         6 |         557 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:3'  |
| mysql-bin.000002 |  557 | Query          |         6 |         652 | use `db4`; create table t1(id int)                                 |
| mysql-bin.000002 |  652 | Gtid           |         6 |         717 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:4'  |
| mysql-bin.000002 |  717 | Query          |         6 |         788 | BEGIN                                                              |
| mysql-bin.000002 |  788 | Table_map      |         6 |         832 | table_id: 237 (db4.t1)                                             |
| mysql-bin.000002 |  832 | Write_rows     |         6 |         882 | table_id: 237 flags: STMT_END_F                                    |
| mysql-bin.000002 |  882 | Xid            |         6 |         913 | COMMIT /* xid=16 */                                                |
| mysql-bin.000002 |  913 | Gtid           |         6 |         978 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:5'  |
| mysql-bin.000002 |  978 | Query          |         6 |        1073 | use `db4`; create table t2(id int)                                 |
| mysql-bin.000002 | 1073 | Gtid           |         6 |        1138 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:6'  |
| mysql-bin.000002 | 1138 | Query          |         6 |        1233 | use `db4`; create table t3(id int)                                 |
| mysql-bin.000002 | 1233 | Gtid           |         6 |        1298 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:7'  |
| mysql-bin.000002 | 1298 | Query          |         6 |        1369 | BEGIN                                                              |
| mysql-bin.000002 | 1369 | Table_map      |         6 |        1413 | table_id: 238 (db4.t3)                                             |
| mysql-bin.000002 | 1413 | Write_rows     |         6 |        1458 | table_id: 238 flags: STMT_END_F                                    |
| mysql-bin.000002 | 1458 | Xid            |         6 |        1489 | COMMIT /* xid=19 */                                                |
| mysql-bin.000002 | 1489 | Gtid           |         6 |        1554 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:8'  |
| mysql-bin.000002 | 1554 | Query          |         6 |        1667 | use `db4`; DROP TABLE `t3` /* generated by server */               |
| mysql-bin.000002 | 1667 | Gtid           |         6 |        1732 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:9'  |
| mysql-bin.000002 | 1732 | Query          |         6 |        1803 | BEGIN                                                              |
| mysql-bin.000002 | 1803 | Table_map      |         6 |        1847 | table_id: 239 (db4.t2)                                             |
| mysql-bin.000002 | 1847 | Write_rows     |         6 |        1892 | table_id: 239 flags: STMT_END_F                                    |
| mysql-bin.000002 | 1892 | Xid            |         6 |        1923 | COMMIT /* xid=21 */                                                |
| mysql-bin.000002 | 1923 | Gtid           |         6 |        1988 | SET @@SESSION.GTID_NEXT= '98ddc71a-b12d-11eb-b85f-000c29b6f740:10' |
| mysql-bin.000002 | 1988 | Query          |         6 |        2077 | drop database db4                                                  |
+------------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+

-- 3.筛选需要的GTID号 - 2~9 不要8
-- 4.截取日志 
mysqlbinlog --skip-gtids --include-gtids='98ddc71a-b12d-11eb-b85f-000c29b6f740:2-9' --exclude-gtids='98ddc71a-b12d-11eb-b85f-000c29b6f740:8' /data/mysql/3306/logs/binlog/mysql-bin.000002 > /tmp/gtid.sql


参数:

  • --skip-gtids : 截取的数据导出到文件时,忽略掉GTID,那么在恢复时,MySQL就会认为是新操作,达到数据恢复的目的
  • --include-gtids : 截取日志包括的gtid号
  • --exclude-gtids : 截取日志不包含的gtid号, 多个逗号分隔

3. 恢复数据

-- 关闭binlog日志服务
set sql_log_bin=0;
-- 数据恢复
source /tmp/gtid.sql;
-- 恢复binlog日志服务
set sql_log_bin=1;

-- 查看db4数据库恢复情况
show databases;
select * from db4.t1;

5.日志过期策略

我们还需要了解如何清理bin log,也就是了解bin log日志的过期策略

首先,不能使用系统的rm或者别的手段来清理日志,而是要采用MySQL的命令来清理日志

自动清理

-- 查看 0代表永不过期
mysql> select @@expire_logs_days;
+--------------------+
| @@expire_logs_days |
+--------------------+
|                  0 |
+--------------------+

-- 设置过期时间
set global expire_logs_days=15;

-- 或者配置文件设置 vim /etc/my.cnf
[mysqld]
expire_logs_days=15

手动清理

-- 根据当前时间,删除指定天数以前的日志
purge binary logs before now() - interval 3 day;

-- 将指定bin log文件序号前的都删除,如将000010号文件之前的文件都删除
purge binary logs to 'mysql-bin.000010';

如何让bin log文件序号重置从0开始呢?

-- 慎用(禁止)的命令,尤其是主从环境下禁止在主库使用,但单实例情况下可以用
mysql> reset master;
Query OK, 0 rows affected (0.00 sec)

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       154 |
+------------------+-----------+

bin log日志是如何滚动的

这里总结下bin log日志的滚动方式:

  • 重启MySQL时。
  • 当文件大小达到max_binlog_size值的上限时。
-- 默认是1G大小
mysql> select @@max_binlog_size /1024/1024;
+------------------------------+
| @@max_binlog_size /1024/1024 |
+------------------------------+
|                1024.00000000 |
+------------------------------+


  • 通过flush logs;滚动日志。可以设置定时刷新。
  • 备份时,也可以通过参数设置自动滚动。
posted @ 2021-05-24 18:00  十九分快乐  阅读(113)  评论(0编辑  收藏  举报