当MySQL实例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各类文件所在位置以及指定某些初始化参数,这些参数一般定义了某种内存结构有多大等。在默认状况下,MySQL实例会按照必定的顺序在指定的位置进行读取,用户只需经过命令mysql --help | grep my.cnf来寻找便可。mysql
简单地说,能够把数据库参数当作一个键/值(key/value)对。能够经过命令SHOWVARIABLES查看数据库中的全部参数,也能够经过LIKE来过滤参数名。从MySQL5.1版本开始,还能够经过information_schema架构下的GLOBAL_VARIABLES视图来进行查找。sql
MySQL数据库中的参数能够分为两类:动态(dynamic)参数和静态(static)参数。动态参数意味着能够在MySQL实例运行中进行更改,静态参数说明在整个实例生命周期内都不得进行更改,就好像是只读(read only)的。数据库
能够经过SET命令对动态的参数值进行修改,global和session关键字代表该参数的修改是基于当前会话仍是整个实例的生命周期。有些动态参数只能在会话中进行修改,如autocommit;而有些参数修改完后,在整个实例生命周期中都会生效,如binlog_cache_size;而有些参数既能够在会话中又能够在整个实例的生命周期内生效,如read_buffer_size。缓存
须要注意的是,对变量的全局值进行了修改,在此次的实例生命周期内都有效,但MySQL实例自己并不会对参数文件中的该值进行修改。也就是说,在下次启动时MySQL实例仍是会读取参数文件。若想在数据库实例下一次启动时该参数仍是保留为当前修改的值,那么用户必须去修改参数文件。要想知道MySQL全部动态变量的可修改范围,能够参考MySQL官方手册的DynamicSystem Variables的相关内容。服务器
注:在mysql8中,能够经过set persist命令来持久化对全局变量的修改。网络
错误日志文件对MySQL的启动、运行、关闭过程进行了记录。MySQL DBA在遇到问题时应该首先查看该文件以便定位问题。该文件不只记录了全部的错误信息,也记录一些警告信息或正确的信息。用户能够经过命令SHOW VARIABLES LIKE'log_error'来定位该文件。session
慢查询日志(slow log)可帮助DBA定位可能存在问题的SQL语句,从而进行SQL语句层面的优化。例如,能够在MySQL启动时设一个阈值,将运行时间超过该值的全部SQL语句都记录到慢查询日志文件中。DBA天天或每过一段时间对其进行检查,确认是否有SQL语句须要进行优化。架构
有关慢查询的一些配置项以下:并发
查询日志记录了全部对MySQL数据库请求的信息,不管这些请求是否获得了正确的执行。默认文件名为:主机名.log,从MySQL 5.1开始,能够将查询日志的记录放入mysql架构下的general_log表中。异步
二进制日志(binary log)记录了对MySQL数据库执行更改的全部操做,可是不包括SELECT和SHOW这类操做,由于这类操做对数据自己并无修改。
若是用户想记录SELECT和SHOW操做,那只能使用查询日志,而不是二进制日志。此外,二进制日志还包括了执行数据库更改操做的时间等其余额外信息。总的来讲,二进制日志主要有如下几种做用:
经过配置参数log-bin[=name]能够启动二进制日志。若是不指定name,则默认二进制日志文件名为主机名,后缀名为二进制日志的序列号,所在路径为数据库所在目录(datadir)。
如下配置文件参数影响着二进制日志记录的信息和行为:
参数max_binlog_size指定了单个二进制日志文件的最大值,若是超过该值,则产生新的二进制日志文件,后缀名+1,并记录到.index文件。
当使用事务的表存储引擎(如InnoDB存储引擎)时,全部未提交(uncommitted)的二进制日志会被记录到一个缓存中去,等该事务提交(committed)时直接将缓冲中的二进制日志写入二进制日志文件,而该缓冲的大小由binlog_cache_size决定,默认大小为32K。此外,binlog_cache_size是基于会话(session)的,也就是说,当一个线程开始一个事务时,MySQL会自动分配一个大小为binlog_cache_size的缓存,所以该值的设置须要至关当心,不能设置过大。当一个事务的记录大于设定的binlog_cache_size时,MySQL会把缓冲中的日志写入一个临时文件中,所以该值又不能设得过小。经过SHOW GLOBALSTATUS命令查看binlog_cache_use、binlog_cache_disk_use的状态,能够判断当前binlog_cache_size的设置是否合适。binlog_cache_use记录了使用缓冲写二进制日志的次数,binlog_cache_disk_use记录了使用临时文件写二进制日志的次数。
在默认状况下,二进制日志并非在每次写的时候同步到磁盘(用户能够理解为缓冲写)。所以,当数据库所在操做系统发生宕机时,可能会有最后一部分数据没有写入二进制日志文件中,这会给恢复和复制带来问题。参数sync_binlog=[N]表示每写缓冲多少次就同步到磁盘。若是将N设为1,即sync_binlog=1表示采用同步写磁盘的方式来写二进制日志,这时写操做不使用操做系统的缓冲来写二进制日志。sync_binlog的默认值为0,若是使用InnoDB存储引擎进行复制,而且想获得最大的高可用性,建议将该值设为ON。
可是,即便将sync_binlog设为1,仍是会有一种状况致使问题的发生。当使用InnoDB存储引擎时,在一个事务发出COMMIT动做以前,因为sync_binlog为1,所以会将二进制日志当即写入磁盘。若是这时已经写入了二进制日志,可是提交尚未发生,而且此时发生了宕机,那么在MySQL数据库下次启动时,因为COMMIT操做并无发生,这个事务会被回滚掉。可是二进制日志已经记录了该事务信息,不能被回滚。这个问题能够经过将参数innodb_support_xa设为1来解决,虽然innodb_support_xa与XA事务有关,但它同时也确保了二进制日志和InnoDB存储引擎数据文件的同步。
注:二进制日志的写入时机是事务语句完成的时候,此时还未真正执行commit和释放锁。
Binary logging is done immediately after a statement or transaction completes but before any locks are released or any commit is done. This ensures that the log is logged in commit order.
参数binlog-do-db和binlog-ignore-db表示须要写入或忽略写入哪些库的日志。默认为空,表示须要同步全部库的日志到二进制日志。
若是当前数据库是复制中的slave角色,则它不会将从master取得并执行的二进制日志写入本身的二进制日志文件中去。若是须要写入,要设置log-slave-update。若是须要搭建master=>slave=>slave架构的复制,则必须设置该参数。
binlog_format参数十分重要,它影响了记录二进制日志的格式。在MySQL 5.1版本以前,没有这个参数。全部二进制文件的格式都是基于SQL语句(statement)级别的,所以基于这个格式的二进制日志文件的复制(Replication)和Oracle的逻辑Standby有点类似。同时,对于复制是有必定要求的。如在主服务器运行rand、uuid等函数,又或者使用触发器等操做,这些均可能会致使主从服务器上表中数据的不一致(not sync)。另外一个影响是,会发现InnoDB存储引擎的默认事务隔离级别是REPEATABLE READ。这其实也是由于二进制日志文件格式的关系,若是使用READ COMMITTED的事务隔离级别(大多数数据库,如Oracle,Microsoft SQL Server数据库的默认隔离级别),会出现相似丢失更新的现象,从而出现主从数据库上的数据不一致。
MySQL 5.1开始引入了binlog_format参数,该参数可设的值有STATEMENT、ROW和MIXED。
1)表的存储引擎为NDB,这时对表的DML操做都会以ROW格式记录。
2)使用了UUID()、USER()、CURRENT_USER()、FOUND_ROWS()、ROW_COUNT()等不肯定函数。
3)使用了INSERT DELAY语句。
4)使用了用户定义函数(UDF)。
5)使用了临时表(temporary table)。
在一般状况下,咱们将参数binlog_format设置为ROW,这能够为数据库的恢复和复制带来更好的可靠性。可是不能忽略的一点是,这会带来二进制文件大小的增长,有些语句下的ROW格式可能须要更大的容量。而因为复制是采用传输二进制日志方式实现的,所以复制的网络开销也有所增长。
二进制日志文件不能像错误日志文件、慢查询日志文件那样用cat、head、tail等命令来查看。要查看二进制日志文件的内容,必须经过MySQL提供的工具mysqlbinlog。
InnoDB采用将存储的数据按表空间(tablespace)进行存放的设计。在默认配置下会有一个初始大小为10MB,名为ibdata1的文件。该文件就是默认的表空间文件(tablespace file),用户能够经过参数innodb_data_file_path对其进行设置,用户能够经过多个文件组成一个表空间,同时制定文件的属性,如:
[mysqld] innodb_data_file_path = /db/ibdata1:2000M;/dr2/db/ibdata2:2000M:autoextend
这里将/db/ibdata1和/dr2/db/ibdata2两个文件用来组成表空间。若这两个文件位于不一样的磁盘上,磁盘的负载可能被平均,所以能够提升数据库的总体性能。同时,两个文件的文件名后都跟了属性,表示文件idbdata1的大小为2000MB,文件ibdata2的大小为2000MB,若是用完了这2000MB,该文件能够自动增加(autoextend)。
设置innodb_data_file_path参数后,全部基于InnoDB存储引擎的表的数据都会记录到该共享表空间中。若设置了参数innodb_file_per_table,则用户能够将每一个基于InnoDB存储引擎的表产生一个独立表空间。独立表空间的命名规则为:表名.ibd。经过这样的方式,用户不用将全部数据都存放于默认的表空间中。
须要注意的是,这些单独的表空间文件仅存储该表的数据、索引和插入缓冲BITMAP等信息,其他信息仍是存放在默认的表空间中。下图显示了InnoDB存储引擎对于文件的存储方式:
在默认状况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件。在MySQL官方手册中将其称为InnoDB存储引擎的日志文件,不过更准确的定义应该是重作日志文件(redo log file)。重作日志文件对于InnoDB存储引擎相当重要,它们记录了对于InnoDB存储引擎的事务日志。
当实例或介质失败(media failure)时,重作日志文件就能派上用场。例如,数据库因为所在主机掉电致使实例失败,InnoDB存储引擎会使用重作日志恢复到掉电前的时刻,以此来保证数据的完整性。
每一个InnoDB存储引擎至少有1个重作日志文件组(group),每一个文件组下至少有2个重作日志文件,如默认的ib_logfile0和ib_logfile1。为了获得更高的可靠性,用户能够设置多个的镜像日志组(mirrored log groups),将不一样的文件组放在不一样的磁盘上,以此提升重作日志的高可用性。在日志组中每一个重作日志文件的大小一致,并以循环写入的方式运行。InnoDB存储引擎先写重作日志文件1,当达到文件的最后时,会切换至重作日志文件2,再当重作日志文件2也被写满时,会再切换到重作日志文件1中。
下列参数影响着重作日志文件的属性:
参数innodb_log_file_size指定每一个重作日志文件的大小。在InnoDB1.2.x版本以前,重作日志文件总的大小不得大于等于4GB,而1.2.x版本将该限制扩大为了512GB。
参数innodb_log_files_in_group指定了日志文件组中重作日志文件的数量,默认为2。参数innodb_mirrored_log_groups指定了日志镜像文件组的数量,默认为1,表示只有一个日志文件组,没有镜像。若磁盘自己已经作了高可用的方案,如磁盘阵列,那么能够不开启重作日志镜像的功能。最后,参数innodb_log_group_home_dir指定了日志文件组所在路径,默认为./,表示在MySQL数据库的数据目录下。
重作日志文件的大小设置对于InnoDB存储引擎的性能有着很是大的影响。一方面重作日志文件不能设置得太大,若是设置得很大,在恢复时可能须要很长的时间;另外一方面又不能设置得过小了,不然可能致使一个事务的日志须要屡次切换重作日志文件。此外,重作日志文件过小会致使频繁地发生async checkpoint,致使性能的抖动。
重作日志有一个capacity变量,该值表明了最后的检查点不能超过这个阈值,若是超过则必须将缓冲池(innodb buffer pool)中脏页列表(flush list)中的部分脏数据页写回磁盘,这时会致使用户线程的阻塞。
一样是记录事务日志,和以前介绍的二进制日志有什么区别?
首先,二进制日志会记录全部与MySQL数据库有关的日志记录,包括InnoDB、MyISAM、Heap等其余存储引擎的日志。而InnoDB存储引擎的重作日志只记录有关该存储引擎自己的事务日志。
其次,记录的内容不一样,不管用户将二进制日志文件记录的格式设为STATEMENT仍是ROW,又或者是MIXED,其记录的都是关于一个事务的具体操做内容,即该日志是逻辑日志。而InnoDB存储引擎的重作日志文件记录的是关于每一个页(Page)的更改的物理状况。
此外,写入的时间也不一样,二进制日志文件仅在事务提交前进行提交,即只写磁盘一次,不论这时该事务多大。而在事务进行的过程当中,却不断有重作日志条目(redo entry)被写入到重作日志文件中。
从重作日志缓冲往磁盘写入时,是按512个字节,也就是一个扇区的大小进行写入。由于扇区是写入的最小单位,所以能够保证写入一定是成功的。所以在重作日志的写入过程当中不须要有doublewrite。
从日志缓冲写入磁盘上的重作日志文件是按必定条件进行的,主线程中每秒会将重作日志缓冲写入磁盘的重作日志文件中,不论事务是否已经提交。另外一个触发写磁盘的过程是由参数innodb_flush_log_at_trx_commit控制,表示在提交(commit)操做时,处理重作日志的方式。
参数innodb_flush_log_at_trx_commit的有效值有0、一、2。0表明当提交事务时,并不将事务的重作日志写入磁盘上的日志文件,而是等待主线程每秒的刷新。1和2不一样的地方在于:1表示在执行commit时将重作日志缓冲同步写到磁盘,即伴有fsync的调用。2表示将重作日志异步写到磁盘,即写到文件系统的缓存中。所以不能彻底保证在执行commit时确定会写入重作日志文件,只是有这个动做发生。
所以为了保证事务的ACID中的持久性,必须将innodb_flush_log_at_trx_commit设置为1,也就是每当有事务提交时,就必须确保事务都已经写入重作日志文件。那么当数据库由于意外发生宕机时,能够经过重作日志文件恢复,并保证能够恢复已经提交的事务。而将重作日志文件设置为0或2,都有可能发生恢复时部分事务的丢失。不一样之处在于,设置为2时,当MySQL数据库发生宕机而操做系统及服务器并无发生宕机时,因为此时未写入磁盘的事务日志保存在文件系统缓存中,当恢复时一样能保证数据不丢失。