以前这篇文章MySQL配置基础简要说明了MySQL的配置基础,包括配置文件的位置、配置项的分段、配置变量的生效、以及配置变量和状态变量的查看,对MySQL的配置有了一个基础。
如今则会进一步了解更多底层原理,搞清楚更多配置的含义和做用。html
本文为《高性能MySQL》读书笔记,配合文档查阅更佳: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html
InnoDB在每一个事务提交的时候,不会把缓冲池的内容当即刷到磁盘。而是从缓冲池将事务记录到事务日志中,输出日志(持久化),再由事务日志完成写磁盘的操做。
事务日志会把数据文件的随机I/O转换成几乎顺序的I/O,并且把刷新到磁盘的操做转移到后台,从而让查询更快。
事务日志有固定的大小,采用环形方式写(写到末尾时跳转到开头继续写)。按期将缓冲池传来的事务经过日志方式持久化,再将脏数据刷到磁盘中。mysql
缓冲池 <--> 事务日志 <--> 磁盘
先将事务变成日志,写入磁盘(持久化),再慢慢根据日志内容写入磁盘。
事务日志依赖innodb_log_file_size和innodb_log_files_in_groups这两个变量。前者声明每一个日志文件的大小,后者声明日志文件的个数。
InnoDB会使用多个日志文件做为循环日志(1号文件写完了写2号,2号写完了写1号)sql
默认是50M,2个文件。共100M。建议增大单个文件的大小,仍然使用2个文件。(本文使用MySQL 8.0.21 不一样版本默认参数可能不一致)
mysql> show variables where variable_name like "%inno%log_file%"; +---------------------------+----------+ | Variable_name | Value | +---------------------------+----------+ | innodb_log_file_size | 52428800 | | innodb_log_files_in_group | 2 | +---------------------------+----------+
事务日志,将事务写入日志文件的时候,也并非直接写入的,而是使用写入缓存。先写入缓存中,再由缓存按期写入文件。由innodb_log_buffer_size 参数决定使用写入缓存大小。
如下3个条件,知足任一条件就会刷新缓存到日志文件中。数据库
MySQL 8.0.21 默认大小为16M。因为最长每1秒会刷新一次写入缓存,因此这个参数不用设置的过大,只须要超过每秒产生的事务量便可。
mysql> show variables where variable_name like "%inno%log_b%"; +------------------------+----------+ | Variable_name | Value | +------------------------+----------+ | innodb_log_buffer_size | 16777216 | +------------------------+----------+
InnoDB和磁盘的读写交互都经过innodb_flush_method来选择。主要有以下几种:segmentfault
一、fdatasync():和fsync()相似,可是只刷新文件数据自己,不包括元数据。并且,这个选项会使用使用双重缓冲(包括操做系统这一层的缓存)
二、O_DIRECT:依然使用fsync()来刷新文件到磁盘,可是会关闭操做系统缓存,告知操做系统不要缓存且不要预读。(全部读写都直接到达存储设备,避免双重缓冲)缓存
这个设置只会影响操做系统,不会影响RAID卡的预读。
若是使用这个选项,最好使用带预读的RAID卡,且打开写回(write_back)
三、O_DSYNC
这个选项会使全部写同步,或者说,只有数据确切写到磁盘后,写操做才会返回。
每一个write()或pwrite()操做都会函数完成前将数据同步到磁盘,且这个过程是阻塞的。[而fsync()容许积累写操做到缓存,再一次性刷新数据。]安全
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_method
更多可参考: https://www.cnblogs.com/CNty/p/10943626.html
InnoDB I/O配置文档: https://dev.mysql.com/doc/refman/5.7/en/optimizing-innodb-diskio.html
表空间的本质是一个虚拟文件系统,由多个文件组成。InnoDB用表空间实现了不少功能,不只有存储表和索引,还有回滚日志,插入缓存(Insert Buffer),双写缓冲(Doublewrite Buffer)等。服务器
可使用以下2个参数来配置表空间。async
下面是一个例子函数
innodb_data_home_dir = /var/lib/mysql/ innodb_data_file_path = ibdata1:1G;ibdata2;1G;ibdata3:1G
PS:innodb_data_home_dir的默认值是空,和MySQL的data
同目录。
The default value is the MySQL data
directory.(也就是datadir
变量。
mysql> show variables where variable_name like "datadir"; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | datadir | /var/lib/mysql/ | +---------------+-----------------+ 1 row in set (0.00 sec)
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_data_home_dir
定制表空间文件时,能够选择使用autoextend来让表空间能够自动扩展,即便超过了分配的空间。(可是一旦扩展了就很难收缩, 不建议使用extend)
回收空间的惟一办法就是导出数据、重启MySQL、重建、再从新导入。(或者说,无法在不从新导入所有数据的前提下给共享表空间瘦身。
innodb_file_per_table 可让InnoDB为每张表使用一个文件。另外,即便打开这个选项,依旧会为回滚日志和其余系统数据使用共享表空间(也就是说,这个选项主要是针对业务的表,将其分文件存储。系统数据仍是使用默认的共享表空间)
注意,使用独立表空间会致使一个问题,DROP TABLE性能会不好。 可能会致使服务器阻塞。
建议:打开innodb_file_per_table,每一个数据表一个文件。而且关闭共享表空间的自动扩展。
毕竟每一个表一个文件,管理起来仍是好不少。只要没有大量的小表。再加上DROP TABLE的性能差。换句话说,也就是表数量没有太大变更+没有大量小表,就很适合用独立表空间。
磁盘和InnoDB交互期间,都会先写入双写缓冲,再写入目标(本质上,双写缓冲就是一个最近写回的页面的备份拷贝。
因为InnoDB写页面到双写缓冲时,是 顺序写入的,因此性能影响并无那么大。
Disk --> DoubleWrite --> InnoDB 若是写入到双写缓冲时不完整,可是磁盘中一定是有完整数据的。出现问题时可恢复。 若是写入到InnoDB时不完整,能够用双写缓冲的数据验证。 InnoDB --> DoubleWrite --> Disk 与上述相似,双写缓冲会保证数据可恢复。
可使用innodb_doubewrite来设置为0来关闭双写(这对于备库比较合适)
max_connect_errors:若是某个主机连续x个链接失败,则会被BAN掉。一旦被BAN,只能命令刷新缓存才能解除。不建议设置的太小,以避免出现全部应用程序被BAN的状况。
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_connect_errors
备库日志同步写磁盘相关:
【这3个变量都是动态变量,一旦设置,会当即对全部备库生效。】
sync_master_info:每有x个事件发生,就将 master.info 向磁盘同步写一次。【使用fdatasync() 】
https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_sync_master_info
sync_relay_log:每有x个事件被写入relay log,就将 relay log 向磁盘同步写一次。【使用fdatasync() 】
https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_sync_relay_log
sync_relay_log_info:与上一个相似,每x个事件发生后,就将 relay-log.info 向磁盘同步写一次。
https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_sync_relay_log_info
max_connections
更像是紧急刹车,保证数据库不会由于应用程序链接数突增致使自身不堪重负。(保护数据库自己)当出现问题,致使新建过多新链接时,把多余的错误连接拒绝掉,是一种快速、低代价的失败方式。
这个参数应该设置的足够高(能够处理正常状况下的负载,服务正常运行),其次也要足够安全(保证能够登陆上服务器,进行维护操做)
好比,正常状况下有300链接数,那么这个值必然不能低于300(保证服务正常运行),能够考虑400~500.
本文主要是对MySQL配置项进行了进一步学习,主要有InnoDB的IO以及Inno表空间配置(共享表空间和独立表空间的了解),还有一些常见的配置、安全相关的配置、以及备库相关配置。MySQL的配置项不少,很是灵活,有些还能动态生效。因此更须要深刻了解才能更好的使用。这是一个持续的过程。