MySQL日志
MySQL日志记录了MySQL数据库日常操作和错误信息。MySQL有不同类型的日志文件(各自存储了不同类型的日志),从日志当中可以查询到MySQL数据库的运行情况、用户的操作、错误的信息等。
MySQL的日志分为四大类:
- 错误日志:记录MySQL服务的启动、运行或停止MySQL服务时出现的问题;
- 查询日志:记录建立的客户端的连接和执行的语句;
- 二进制日志:记录所有更改数据的语句,可以用于数据的复制;
- 慢查询日志:记录所有执行时间超过long_query_time的所有查询或不使用索引的查询;
默认情况下,所有日志创建于MySQL数据目录中,通过刷新日志,可以强制MySQL关闭或重新打开日志文件,Flush logs
刷新日志或者执行mysqladmin flush-logs
。如果正使用MySQL复制功能,在复制服务器上可以维护更多日志文件,这种日志我们成为接替日志。启动日志功能会降低MySQL数据库的性能。
查询系统设置
mysql> show global variables\G
mysql> show global variables like '%log%';
#查看全局的系统状态
mysql> show session variables\G
mysql> show session variables like '%log%';
#查看当前会话的系统状态
若要修改上面查看出来的参数,可以在MySQL的主配置文件中的mysqld字段中写入即可,如:binlog_cache_size = 1M
。又或者可以在MySQL数据库中进行临时修改:set global binlog_cache_size = 1048576
,这种临时修改在MySQL重启后就会失效。
查看运行状态
mysql> show global status\G
#查看全局的运行状态
mysql> show session status;
#查看当前会话的运行状态
[root@mysql ~]# mysql -V
mysql> status;
mysql> select version();
#查看MySQL的版本
一、错误日志
在MySQL数据库中,错误日志功能是默认开启的。默认情况下,错误日志存储在MySQL数据库的数据目录中。
错误日志文件通常的名称为hostname.err
,其中。hostname
表示服务器主机名。
错误日志信息可以自己进行配置的,错误日志所记录的信息是可以通过log-err
和log-warnings
来定义的。其中log-err
是定义是否启用错误日志的功能和错误日志的存储位置,log-warnings
是定义是否将警告信息也定义到错误日志中。
默认情况下错误日志大概记录以下信息:
- 服务器启动和关闭过程中的信息(未必是错误信息,如mysql如何启动InnoDB的表空间文件的、如何初始化自己的存储引擎等等信息);
- 服务运行过程中的错误信息、时间调度器运行一个事件时产生的信息;
- 在从服务器上启动服务器进程时产生的信息;
- MySQL有很多系统变量是可以设置,系统变量设置不同,会导致系统运行状态的不同。因此mysql提供两组命令,分别查看系统设置和运行状态;
1.1查看错误日志
一般而言,日志级别的定义没有会话变量都只是在全局级别下定义错误日志的状态:
mysql> show global variables like '%log_error%';
+---------------------+----------------------------------+
| Variable_name | Value |
+---------------------+----------------------------------+
| binlog_error_action | ABORT_SERVER |
| log_error | /usr/local/mysql/data/mysqld.err |
| log_error_verbosity | 3 |
+---------------------+----------------------------------+
其中,log_error定义错误日志文件路径, log_error_verbosity值的含义如下:
Verbosity | message |
---|---|
1 | Error only |
2 | Error and warnings |
3 | Error、warnings、notes(defult) |
1.2 定义错误日志
错误日志的存放路径在mysql主配置文件中指定,如下:
[root@db01 ~]# cat /etc/my.cnf
[mysqld]
log-error=/usr/local/mysql/data/mysqld.err
为了方便维护需要,有时会希望将错误日志中的内容做备份并重新开始记录,这时就可以利用MySQL的flush logs
命令来告诉MySQL备份旧日志并生成新的日志文件。备份文件名以“.old”结尾。
1.3 删除错误日志
在mysql 5.5版本之前,数据库管理员可以删除很长时间之前的错误日志,来保证mysql服务器上的硬盘空间。
mysql数据库中,可以使用mysqladmin
命令开启新的错误日志。mysqladmin命令的语法如下:mysqladmin –u root –p flush-logs
也可以登录mysql数据库中使用FLUSH LOGS语句来开启新的错误日志。
在mysql 5.5 版本之后哦,服务器将关闭此项功能,只能使用重命名原来的错误日志文件,手动冲洗日志创建一个新的日志文件,方法如下:
[root@db01 ~]# cd /usr/local/mysql/data/
[root@db01 data]# mv mysqld.err{,.old}
[root@db01 data]# mysqladmin -uroot -p123 flush-logs
二、二进制日志
二进制日志主要记录MySQL数据库的变化,二进制日志以一种有效的格式,并且是事务安全的方式包含更新日志中可用的信息。二进制日志包含了所有更新了数据或者已经潜在更新了数据。还包含关于每个更新数据库的语句和执行时间,它不包含没有修改任何数据的语句。使用二进制日志的主要目的是最大可能的恢复数据库。
2.1 启用二进制日志
默认情况下是关闭的!
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
log-bin=/usr/local/mysql/data/binary_log #指定二进制日志存放路径及名称
expire_logs_days=10 #保存日志的时间
max_binlog_size=100M #单个日志文件的大小限制
[root@db01 ~]# systemctl restart mysqld
[root@db01 ~]# ll /usr/local/mysql/data/binary_log.*
-rw-r----- 1 mysql mysql 154 4月 15 11:48 /usr/local/mysql/data/binary_log.000001
-rw-r----- 1 mysql mysql 40 4月 15 11:48 /usr/local/mysql/data/binary_log.index
[root@db01 ~]# mysql -uroot -p123
mysql> show variables like 'log_%';
+----------------------------------------+----------------------------------------+
| Variable_name | Value |
+----------------------------------------+----------------------------------------+
| log_bin | ON |
| log_bin_basename | /usr/local/mysql/data/binary_log |
| log_bin_index | /usr/local/mysql/data/binary_log.index |
2.2 查看二进制日志
MySQL二进制日志存储了所有的变更信息,MySQL二进制日志经常使用。当MySQL创建二进制日志文件时,首先创建一个以’filename’为名称,以’.index’为后缀的文件;再创建一个以’filename’为名称,以’.000001’为后缀的文件。当MySQL服务重启一次,以’.000001’为后缀的文件会增加一个,并且后缀名加1递增。如果日志长度超过max_binlog_size的上限,也会创建一个新的日志。 show binary logs;
可以查看当前的二进制日志文件个数及其文件名。
二进制日志并不能直接查看,如果想要查看日志内容,可以通过mysqlbinlog
命令查看:
mysql> show binary logs; #查看当前的二进制日志文件个数及其文件名
+-------------------+-----------+
| Log_name | File_size |
+-------------------+-----------+
| binary_log.000001 | 154 |
+-------------------+-----------+
[root@db01 ~]# mysqlbinlog /usr/local/mysql/data/binary_log.000001
#查看日志内容
2.3 删除二进制日志
MySQL的二进制文件可以配置自动删除,同时MySQL提供了手动删除二进制文件的方法:
- RESET MASTER:删除所有的二进制日志文件;
- PURGE MASTER LOGS:只删除部分二进制日志文件;
- Reset master:删除所有二进制日志 ;
- Purge master logs to ‘二进制名’ :删除单个二进制日志之前的;
mysql> purge master logs to 'binary_log.000001';
#删除..01之前的二进制日志文件
mysql> purge master logs before '20180101';
#删除2018-01-01之前的日志文件
三、事务日志
事务日志(InnoDB特有的日志,因为只有Innodb支持事务)可以帮助提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘。事务日志采用追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说要快得多。事务日志持久以后,内存中被修改的数据在后台可以慢慢的刷回到磁盘。目前大多数的存储引擎都是这样实现的。 如果数据的修改已经记录到事务日志并持久化,但数据本身还没有写回磁盘,此时系统崩溃,存储引擎在重启时能够自动恢复这部分修改的数据。具有的恢复方式则视存储引擎而定。
3.1 查看事务日志
mysql> show global variables like 'innodb_lo%';
+--------------------------------+----------+
| Variable_name | Value |
+--------------------------------+----------+
| innodb_lock_wait_timeout | 50 |
| innodb_locks_unsafe_for_binlog | OFF |
| innodb_log_buffer_size | 16777216 |
| innodb_log_checksums | ON |
| innodb_log_compressed_pages | ON |
| innodb_log_file_size | 50331648 | #日志文件大小
| innodb_log_files_in_group | 2 | #DB中设置几组事务日志,默认是2
| innodb_log_group_home_dir | ./ | #定义innodb事务日志组的位置,此位置设置默认为MySQL的datadir
| innodb_log_write_ahead_size | 8192 |
+--------------------------------+----------+
| innodb_flush_log_at_trx_commit | 1 #在事务提交时innodb是否同步日志从缓冲区到文件中,当这个值为1(默认值)之时,在每个事务提交时,日志缓冲被写到日志文件,对日志文件做到磁盘操作的刷新,性能会很差造成大量的磁盘I/O但这种方式最安全;如果设为2,每次提交事务都会写日志,但并不会执行刷的操作。每秒定时会刷到日志文件。要注意的是,并不能保证100%每秒一定都会刷到磁盘,这要取决于进程的调度。每次事务提交的时候将数据写入事务日志,而这里的写入仅是调用了文件系统的写入操作,而文件系统是有缓存的,所以这个写入并不能保证数据已经写入到物理磁盘。设置为0,日志缓冲每秒一次地被写到日志文件,并且对日志文件做到磁盘操作的刷新,但是在一个事务提交不做任何操作。
刷写的概念:
刷写其实是两个操作,刷(flush)和写(write),区分这两个概念是很重要的。在大多数的操作系统中,把Innodb的log buffer(内存)写入日志(调用系统调用write),只是简单的把数据移到操作系统缓存中,操作系统缓存同样指的是内存。并没有实际的持久化数据。
所以,通常设为0和2的时候,在崩溃或断电的时候会丢失最后一秒的数据,因为这个时候数据只是存在于操作系统缓存。之所以说“通常”,可能会有丢失不只1秒的数据的情况,比如说执行flush操作的时候阻塞了。
总结:设为1当然是最安全的,但性能页是最差的(相对其他两个参数而言,但不是不能接受)。如果对数据一致性和完整性要求不高,完全可以设为2,如果只最求性能,例如高并发写的日志服务器,设为0来获得更高性能。
每个事务日志都是大小为50兆的文件(不同版本的mysql有差异): 在mysql中默认以ib_logfile0,ib_logfile1名称存在。
四、慢查询日志
顾名思义,慢查询日志中记录的是执行时间较长的query,也就是我们常说的slow query。 慢查询日志采用的是简单的文本格式,可以通过各种文本编辑器查看其中的内容。其中记录了语句执行的时刻,执行所消耗的时间,执行用户,连接主机等相关信息。 慢查询日志的作用: 慢查询日志是用来记录执行时间超过指定时间的查询语句。通过慢查询日志,可以查找出哪些查询语句的执行效率很低,以便进行优化。一般建议开启,它对服务器性能的影响微乎其微,但是可以记录mysql服务器上执行了很长时间的查询语句。可以帮助我们定位性能问题的。MySQL 还提供了专门用来分析满查询日志的工具程序mysqldumpslow,用来帮助数据库管理人员解决可能存在的性能问题。
4.1 查看慢日志的定义
mysql> show global variables like '%slow_query_log%';
#查询慢查询日志是否开启
+---------------------+-------------------------------------+
| Variable_name | Value |
+---------------------+-------------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /usr/local/mysql/data/db01-slow.log |
+---------------------+-------------------------------------+
#OFF表示未开启,下面表示文件存放的路径
mysql> show global variables like '%long%';
#查看如何定义语句为慢查询语句
+----------------------------------------------------------+-----------+
| Variable_name | Value |
+----------------------------------------------------------+-----------+
| long_query_time | 10.000000 |
| performance_schema_events_stages_history_long_size | 10000 |
| performance_schema_events_statements_history_long_size | 10000 |
| performance_schema_events_transactions_history_long_size | 10000 |
| performance_schema_events_waits_history_long_size | 10000 |
+----------------------------------------------------------+-----------+
#long_query_time的值就是慢查询超时时间,默认为10s,只要执行耗时超过10s的语句就被定义为慢查询语句
4.2 启动和设置慢查询日志
① 启动慢查询日志记录
方法一
[root@db01 ~]# vim /etc/my.cnf
#编辑主配置文件,在mysqld字段下写入以下几行
[mysqld]
slow_query_log=1 # 1表示开启慢查询
slow_query_log_file=/usr/local/mysql/data/mysql-slow.log #指定慢查询日志位置
long_query_time=0.0001 #指定超时时间,也就是超过这个时间就会被记录到慢查询日志
slow_launch_time=1 #如果建立线程花费了比这个值更长的时间,slow_launch_threads计数器将增加
[root@db01 ~]# systemctl restart mysqld #重启服务使配置生效
mysql> show global variables like '%slow_query_log%';
+---------------------+--------------------------------------+
| Variable_name | Value |
+---------------------+--------------------------------------+
| slow_query_log | ON |
| slow_query_log_file | /usr/local/mysql/data/mysql-slow.log |
+---------------------+--------------------------------------+
#慢查询日志功能已经开启
mysql> show global variables like '%long%';
+----------------------------------------------------------+----------+
| Variable_name | Value |
+----------------------------------------------------------+----------+
| long_query_time | 0.000100 |
| performance_schema_events_stages_history_long_size | 10000 |
| performance_schema_events_statements_history_long_size | 10000 |
| performance_schema_events_transactions_history_long_size | 10000 |
| performance_schema_events_waits_history_long_size | 10000 |
+----------------------------------------------------------+----------+
#修改的参数已经生效
方法二
mysql> set global slow_query_log=1;
mysql> set global long_query_time=0.0001;
global表示全局生效,还有一个选项就是session,表示仅在当前会话生效,其区别是,session在退出当前会话后就会被重置,global则是在重启MySQL服务后才会重置,而方法1中写入配置文件中的方式则是永久生效!
注意:如果主配置文件中定义了long_query_time的值,并且MySQL命令行中使用set指令又定义了long_query_time的值,则配置文件中定义的值优先生效。
② 查看慢查询日志
若想要查询到慢查询日志,必须保证两点,首先是将慢查询的超时时间设置的短一些,比如我在上面设置为了0.0001,只要查询的时间超过了这个值,则被定义为慢查询。(为了验证效果,在生产环境中还是要结合实际情况)。第二呢,就是在开启慢查询后还需要执行几条查询语句,以便产生日志记录信息(自己随便查询两句吧)。
[root@db01 ~]# mysqldumpslow /usr/local/mysql/data/mysql-slow.log
#使用mysqldumpslow工具查看慢查询日志
mysqldumpslow工具常用指令:
使用选项进行查看:
[root@db01 ~]# mysqldumpslow -t 2 -a -s c /usr/local/mysql/data/mysql-slow.log
#以次数来排序,查询前两条,并且显示语句的所有内容
五、数据文件
在MySQL 中每一个数据库都会在定义好(或者默认)的数据目录下存在一个以数据库名字命名的文件夹,用来存放该数据库中各种表数据文件。不同的MySQL 存储引擎有各自不同的数据文件。如MyISAM 用“.MYD”作为扩展名,Innodb 用“.ibd”,Archive 用“.arc”,CSV 用“.csv”,等等。
“.frm”文件 与表相关的元数据(meta)信息都存放在“.frm”文件中,包括表结构的定义信息等。不论是什么存储引擎(MySQL常用的两个存储引擎是MyISAM和InnoDB),每一个表都会有一个以表名命名的“.frm”文件。所有的“.frm”文件都存放在所属数据库的文件夹下面。
MyISAM数据库表文件
.MYD文件:表数据文件;.MYI文件:索引文件
- “.MYD”文件 “.MYD”文件是MyISAM存储引擎专用,存放MyISAM 表的数据。每一个MyISAM 表都会有一个“.MYD”文件与之对应,同样存放于所属数据库的文件夹下,和“.frm”文件在一起;
- “.MYI”文件 “.MYI”文件也是专属于MyISAM 存储引擎的,主要存放MyISAM 表的索引相关信息。对于MyISAM 存储来说,可以被cache 的内容主要就是来源于“.MYI”文件中。每一个MyISAM 表对应一个“.MYI”文件,存放于位置和“.frm”以及“.MYD”一样;
Innodb数据库表文件
InnoDB采用表空间(tablespace)来管理数据,存储表数据和索引。
- .ibd文件:单表表空间文件,每个表使用一个表空间文件(file per table),存放用户数据库表数据和索引;
- InnoDB共享表空间(即InnoDB文件集,ibfile set):ibdata1、ibdata2等,存储InnoDB系统信息和用户数据库表数据和索引,所有表共用;
- “.ibd”文件和ibdata 文件 这两种文件都是存放Innodb 数据的文件,之所以有两种文件来存放Innodb 的数据(包括索引),是因为Innodb 的数据存储方式能够通过配置来决定是使用共享表空间存放存储数据,还是独享表空间存放存储数据。独享表空间存储方式使用“.ibd”文件来存放数据,且每个表一个“.ibd”文件,文件存放在和MyISAM数据相同的位置;
- 如果选用共享存储表空间来存放数据,则会使用ibdata 文件来存放,所有表共同使用一个(或者多个,可自行配置)ibdata 文件。 ibdata 文件可以通过innodb_data_home_dir 和innodb_data_file_path两个参数共同配置组成, innodb_data_home_dir 配置数据存放的总目录, 而innodb_data_file_path 配置每一个文件的名称。innodb_data_file_path 中可以一次配置多个ibdata 文件。文件可以是指定大小,也可以是自动扩展的,但是Innodb 限制了仅仅只有最后一个ibdata 文件能够配置成自动扩展类型。当我们需要添加新的ibdata 文件的时候,只能添加在innodb_data_file_path配置的最后,而且必须重启MySQL 才能完成ibdata 的添加工作。不过如果我们使用独享表空间存储方式的话,就不会有这样的问题;
总结
共享表空间以及独占表空间都是针对数据的存储方式而言的。
- 共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中;
- 独占表空间: 每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm表描述文件,还有一个.ibd文件。其中这个文件包括了单独一个表的数据内容以及索引内容;
共享表空间优缺点:
- 优点:可以将表空间分成多个文件存放到各个磁盘上。数据和文件放在一起,方便管理;
- 缺点:所有的数据和索引存放到一个文件中,多个表及索引在表空间中混合存储,这样对于一个表做了大量操作后表空间将会有大量的空隙,特别是对于统计分析,日志系统这类应用最不合适用共享表空间;
独立表空间优缺点:
优点:
- 每个表都有自己独立的表空间;
- 每个表的数据和索引都会存在自己的表空间中;
- 可以实现单表在不同的数据库中移动;
- 空间可以回收:
- a) Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:
alter table TableName engine=innodb;
回缩不用的空间; - b)对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理;
- a) Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:
缺点:
- 单表增加过大,如超过100G。相比较之下,使用独立表空间的效率以及性能会更高一点;
5.1 查看当前数据库的表空间管理类型
mysql> show variables like '%innodb_file_per%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
#ON表示独立表空间管理,OFF代表共享表空间管理
#查看单表的表空间管理方式,需要查看每个表是否有单独的数据文件
5.2 修改InnoDB共享表空间
[root@db01 ~]# vim /etc/my.cnf #编辑主配置文件,在mysqld字段下写入以下配置
innodb_file_per_table=0 #0为使用共享表空间,1为独占表空间
innodb_data_file_path=ibdata1:100M:autoextend #设置一个可自动扩展大小,尺寸为100M的数据文件
innodb_data_home_dir=/usr/local/mysql/data #定义共享表空间默认存放路径
[root@db01 ~]# systemctl restart mysqld #启动报错了
[root@db01 ~]# tail -20 /usr/local/mysql/data/mysqld.err
2020-04-15T06:49:39.410299Z 0 [ERROR] InnoDB: The Auto-extending innodb_system data file '/usr/local/mysql/data/ibdata1' is of a different size 768 pages (rounded down to MB) than specified in the .cnf file: initial 6400 pages, max 0 (relevant if non-zero) pages!
#查询错误日志,以上最关键的一行
注:不同版本的mysql报错略有不同,注意看错误日志的内容。大概意思就是设置的pages页为6400,超过了它的最大值768,那么算一下,设置的初始大小100M,pages大小就是6400,则表示1M=64pages,它的最大值是768,也就是说,我们设置初始大小最大可以是768/64=12M。
[root@db01 ~]# vim /etc/my.cnf
innodb_data_file_path=ibdata1:12M:autoextend
[root@db01 ~]# systemctl restart mysqld
#同样,如果还是启动失败,则再次查看错误日志,是否pages页大小设置的还是不合理
5.3 查看修改后数据库的表空间管理类型
mysql> show variables like '%innodb_file_per%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | OFF |
+-----------------------+-------+
#此时状态为OFF,则表示使用的是共享表存储空间,之后创建的表都会使用定义的共享表空间来存储数据。