第三章 文件
构成MySQL数据库和InnoDB存储引擎表的各种类型文件包括:
- 参数文件
- 日志文件
- socket文件
- pid文件
- MySQL表结构文件
- 存储引擎文件
3.1 参数文件
MySQL实例启动时,数据库会先去读取一个配置参数文件,用来寻找数据库的各种文件所在位置以及某些初始化参数。
3.1.1 什么是参数
简单来说就是键值对,在mysql中,可以通过 show variables
来查看数据库中所有的参数
3.1.2 参数类型
MySQL数据库可以分为两类:
- 动态(dynamic)参数
- 静态(static)参数
动态参数意味着可以在MySQL实例运行中进行更改,静态参数说明在整个实例生命周期都不得更改,就好像只读的一样。可以通过SET命令对动态参数值进行修改,SET的语法如下
SET | [global | session] system_var_name = expr | [@@global.|@@session.|@@] system_var_name = expr
可以看到 global 和 session 关键字,他们表明该参数是基于当前会话还是整个实例的生命周期。有些动态参数只能在会话中修改,而有些参数修改完后,整个实例生命周期都会生效,而有些既可以在会话中又可以在这个实例的生命周期内生效。对变量的全局值进行修改,但并不是改变 MySQL 参数文件中的值,下次启动 MySQL ,还是会读取参数文件
3.2 日志文件
日志文件记录了影响 MySQL 数据库的各种类型活动。MySQL
数据库常见的日志文件有:
- 错误日志(error log)
- 慢查询日志(slow query log)
- 二进制日志(bin log)
- 查询日志(log)
3.2.1 错误日志
错误日志文件对MySQL的启动、运行、关闭过程进行了记录。不仅记录错误信息,也记录一些警告信息或正确的信息
3.2.2 慢查询日志
慢查询日志可帮助定位到可能存在问题的 SQL 语句,从而进行SQL语句层面优化。
可以在MySQL启动时通过参数 long_query_time来设置一个阈值,将运行超过(大于)该时间的SQL语句记录到慢查询的日志文件中。在默认情况下,MySQL数据库并不启动慢查询日志。从MySQL5.1开始,long_query_time开始以微秒记录SQL语句运行的时间。默认情况下,慢查询日志并不开启,用户需要手动把参数 log_slow_queries设置为ON
另一个和慢查询日志有关的参数是log_queries_not_using_indexes,如果运行的SQL语句没有使用索引,则该条SQL语句同样被记录在慢查询日志中。
慢查询的表在mysql架构下的名为slow_log的表中。参数log_output指定了慢查询输出的格式,默认是FILE,可以将它设置为TABLE,然后就可以查询mysql架构下的slow_log了
3.2.3 查询日志
查询日志记录了所有对MySQL数据库请求的信息,无论这些请求是否得到了正确的执行。从MySQL5.1开始,可以将查询日志的记录放入mysql架构下的general_log表中
3.2.4 二进制日志
二进制日志记录了对MySQL数据库执行更改的所有操作,但是不包括select和show这类操作,因为这类操作对数据本身没有修改。然而若操作本身并没有导致数据库发生变化,那么该操作可能也会写入二进制日志中。如更新一行不存在的数据
二进制日志主要有以下几种作用:
- 恢复(recovery):某些数据的恢复需要二进制日志,例如在一个数据库全备文件恢复后,用户可以通过二进制日志进行point-in-time的恢复
- 复制(replication):通过复制和执行二进制日志使一台远程的MySQL数据库与一台MySQL数据库进行实时同步
- 审计(audit):用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入的攻击
二进制日志文件在默认情况并没有开启,需要手动指定参数
log-bin [=name]来启动。如果不指定name,则默认二进制日志文件名为主机名
3.3 套接字文件
在UNIX系统下本地连接MySQL可以采用UNIX域套接字方式,这种方式需要一个套接字(socket)文件。套接字文件可由参数socket控制。一般在/tmp目录下,名为mysql.sock
3.4 pid文件
当MySQL实例启动时,会将自己的进程ID写入一个文件中----该文件即为pid文件。该文件可由参数pid_file控制,默认位于数据库目录下,文件名为主机名.pid
3.5 表结构定义文件
因为MySQL插件式存储引擎的关系,MySQL数据的存储是根据表进行的,每个表都会有与之对应的文件。但不论表采用何种存储引擎,MySQL都会有一个以frm为后缀名的文件,这个文件记录了该表的表结构定义。
frm还可以用来存放视图的定义,如用户创建了一个v_a视图,那么对应地会产生一个v_a.frm文件,用来记录视图的定义,该文件是文本文件
3.6 Innodb 存储引擎文件
3.6.1 表空间文件
InnoDB采用将存储的数据按表空间(tablespace)进行存放的设计。在默认配置下,会有一个初始化大小为10MB,名为ibdata1的文件,该文件就是默认的表空间文件,用户可以通过参数innodb_data_file_path对其进行设置,格式如下
innodb_data_file_path = datafile_spec1[;datafile_spec2]
用户可以通过多个文件组成一个表空间,同时制定文件的属性,如
[mysqld]
innodb_data_file_path = /db/ibdata1:2000M;/dr2/db/ibdata2:2000M:autoextend
这里用两个文件组成表空间。若这两个文件位于不同的磁盘上,磁盘的负载可能被平均,提高了数据库的整体性能
设置了 innodb_data_file_path参数后,所有基于InnoDB存储引擎的表的数据都会记录到该共享空间中。若设置了参数innodb_file_per_table,则用户可以将每个基于InnoDB的表产生一个独立表空间。命名规则为表名.ibd。这些单独的表空间文件仅存储该表的数据、索引和插入缓冲BITMAP等信息,其他信息还是存放在默认的表空间中。
3.6.2 重做日志文件
在默认情况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的重做日志文件(redo log file),他们记录了对于InnoDB存储引擎的事务日志。当实例或者介质失败时,重做日志就能派上用场。例如,数据库由于是在主机掉电导致实例失败,InnoDB存储引擎会使用重做日志恢复到掉电以前的时刻,以此来保证数据的完整性。每个InnoDB存储引擎至少有1个重做日志文件组,每个文件组下至少有2个重做日志文件,每个重做日志文件大小一致,并以循环写入的方式运行。下面参数影响着重做日志文件的属性
- innodb_log_file_size :指定了每个重做日志文件的大小
- innodb_log_files_in_group : 指定了重做日志文件组中重做日志文件的数量,默认为2
- innodb_mirrored_log_groups : 指定了日志镜像文件组的数量,默认为1
- innodb_log_group_home_dir : 指定了日志文件组所在路径
重做日志文件大小对于InnoDB存储引擎的性能有着非常大的影响。如果文件设置得很大,在恢复时可能需要很长的时间,又不能设置得太小,否则可能导致一个事务的日志需要多次切换重做日志文件,此外,重做日志文件太小会导致频繁地发生async_checkpoint,导致性能的抖动。
重做日志与二进制日志的区别:
- 二进制日志会记录所有与MySQL数据库有关的日志记录,包括InnoDB,MyISAM,Heap等其他存储引擎的日志。而InnoDB存储引擎的重做日志只记录有关该存储引擎本身的事务日志。
- 其他,记录的内容不同,无论用户将二进制日志文件记录的格式设为statement还是row或者mixed,其记录的都是关于一个事务的具体操作内容,即该日志是逻辑日志。而InnoDB存储引擎的重做日志文件记录的是关于每个也的更改的物理情况
- 写入的时间不同,二进制日志仅在事务提交前进行提交,即只写磁盘一次,不论这是事务有多大。而在事务进行工程中,却不断有重做日志条目被写入到重做日志文件中。
写入重做日志文件的操作不是直接写,而是先写入一个重做日志缓冲(redo log buffer)中,然后按照一定的条件顺序地写入日志文件中。从重做日志缓冲往磁盘写入时,是按512字节,也就是一个扇区的大小进行写入的,因为扇区是最小单位,因此可以保证写入必定是成功的。因此在重做日志写入的成功中不需要doublewrite。
从重做日志缓冲写入磁盘上的重做日志文件是按一定条件进行的,这些条件包括,第一,主线程每秒会将重做日志缓冲写入磁盘的重做日志文件中,不论事务是否提交。第二,触发写磁盘的过程是由参数innodb_flush_log_at_trx_commit控制,表示在提交操作时,处理重做日志的方式。该参数的有效值为0、1、2。0表示当提交事务时,不将事务的重做日志写入磁盘上的日志文件,而是等待主线程每秒的刷新。1和2的区别在于:1表示在执行commit时将重做日志缓冲同步写入到磁盘,即伴有fsync的调用。2表示将重做日志异步写到磁盘,即写到文件系统的缓存中,因此不能完全保证执行commit时肯定会写入重做日志文件,只是有这个动作发生。
因此保证事务的ACID的持久性,必须将innodb_flush_log_at_trx_commit设置为1,那么当数据库因为意外发生宕机时,可以通过重做日志文件恢复,并保证可以恢复已经提交的事务。而设置为0或者2,都有可能发生恢复时部分事务的丢失。不同之处在于,设置2时,当MySQL数据库发生宕机而操作系统及服务器并没有发生宕机时,由于此时未写入磁盘的事务日志保存在文件系统缓存中,当恢复是同样能保证数据不丢失。