【mysql】关于IO/内存方面的一些优化

这里使用的是mysql  Ver 14.14 Distrib 5.6.19, for Linux (i686) using  EditLine wrapperhtml

1、mysql目录文件

ibdata1:系统表空间 包含数据字典、回滚日志/undolog等mysql

(insert buffer segment/double write segment/rollback segment/index segment/dictionary segment/undo segment)sql

ib_logfile0/ib_logfile1:事务日志/redolog数据库

mysql-relay-bin:中继日志安全

binarylog:二进制日志bash

general_log.log:常规日志服务器

mysql_error.log:错误日志网络

slow_query.log:慢日志并发

.ibd:用户表空间-数据文件(insert buffer bitmap page/leaf page segment/none leaf page segment)app

Innodb buffer pool(内存):undo page /insert buffer page/adaptive hash index/index page/lock info/data dictionary

2、mysql线程

FILE IO

--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
 ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
393 OS file reads, 5 OS file writes, 5 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s

innodb后台全部线程

| thread/sql/main                        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/io_handler_thread        | BACKGROUND | YES          |
| thread/innodb/srv_master_thread        | BACKGROUND | YES          |
| thread/innodb/srv_purge_thread         | BACKGROUND | YES          |
| thread/innodb/srv_monitor_thread       | BACKGROUND | YES          |
| thread/innodb/srv_error_monitor_thread | BACKGROUND | YES          |
| thread/innodb/srv_lock_timeout_thread  | BACKGROUND | YES          |
| thread/innodb/page_cleaner_thread      | BACKGROUND | YES          |
| thread/sql/signal_handler              | BACKGROUND | YES          |
| thread/sql/slave_sql                   | BACKGROUND | YES          |
| thread/sql/slave_io                    | BACKGROUND | YES          | 

IO线程分别是insert buffer thread、log thread、read thread、write thread。

在MySQL 5.6.10以后,默认线程处理模型使用执行每一个客户端链接一个线程语句。随着愈来愈多的客户端链接到服务器和执行语句,总体性能下降。线程池插件的提供旨在减小开销,提升性能的其余线程的处理模式。该插件实现了经过有效地管理语句执行线程的大量客户端链接的提升服务器性能的线程池。

InnoDB Plugin版本开始增长了默认IO thread的数量,默认的read thread和write thread分别增大到了4个,而且再也不使用innodb_file_io_threads参数,而是分别使用innodb_read_io_threads和innodb_write_io_threads参数。
 
线程池解决每一个链接模型解决单线程的几个问题
  • Too many thread stacks make CPU caches almost useless in highly parallel execution workloads. The thread pool promotes thread stack reuse to minimize the CPU cache footprint.

  • With too many threads executing in parallel, context switching overhead is high. This also presents a challenging task to the operating system scheduler. The thread pool controls the number of active threads to keep the parallelism within the MySQL server at a level that it can handle and that is appropriate for the server host on which MySQL is executing.

  • Too many transactions executing in parallel increases resource contention. In InnoDB, this increases the time spent holding central mutexes. The thread pool controls when transactions start to ensure that not too many execute in parallel.

3、mysql访问文件流程

Transaction 来自网络

 

 

3、影响IO/内存的一些参数

一、innodb_flush_log_at_trx_commit 设置为2

这参数是指 事务log(ib_logfile0、ib_logfile1)以怎样的方式写入到log buffer

=0 mysql crash 就丢失了,性能最好

buffer pool -> log buffer 每秒 wirte os cache & flush磁盘

=1 不会丢失,效率低

buffer pool -> log buffer 每次 write os cache & flush磁盘

=2  即便mysql崩溃也不会丢数据

buffer pool -> os cache 每秒flush 磁盘

注意:因为进程调度策略问题,这个“每秒执行一次 flush(刷到磁盘)操做”并非保证100%的“每秒

二、sync_binlog

二进制日志(binary log)同步到磁盘的频率。binary log 每写入 sync_binlog 次后,刷写到磁盘。

若是 autocommit 开启,每一个语句都写一次 binary log,不然每次事务写一次。

默认值是 0,不主动同步,而依赖操做系统自己不按期把文件内容 flush 到磁盘

设为 1 最安全,在每一个语句或事务后同步一次 binary log,即便在崩溃时也最多丢失一个语句或事务的日志,但所以也最慢。

大多数状况下,对数据的一致性并无很严格的要求,因此并不会把 sync_binlog 配置成 1,为了追求高并发,提高性能,能够设置为 100 或直接用 0

三、write/read thread

异步IO线程数

innodb_write_io_threads=16
innodb_read_io_threads=16

(该参数须要在配置文件中添加,重启mysql实例起效)脏页写的线程数,加大该参数能够提高写入性能

四、innodb_max_dirty_pages_pct

最大脏页百分数,当系统中脏页所占百分比超过这个值,INNODB就会进行写操做以把页中的已更新数据写入到磁盘文件中。默认75,通常如今流行的SSD硬盘很难达到这个比例。可依据实际状况在75-80之间调节

五、innodb_io_capacity=5000

从缓冲区刷新脏页时,一次刷新脏页的数量。根据磁盘IOPS的能力通常建议设置以下:

SAS 200
SSD 5000
PCI-E 10000-50000

六、innodb_flush_method=O_DIRECT(该参数须要重启mysql实例起效)

控制innodb 数据文件和redo log的打开、刷写模式。有三个值:fdatasync(默认),O_DSYNC,O_DIRECT。

  • fdatasync模式:写数据时,write这一步并不须要真正写到磁盘才算完成(可能写入到操做系统buffer中就会返回完成),真正完成是flush操做,buffer交给操做系统去flush,而且文件的元数据信息也都须要更新到磁盘。

  • O_DSYNC模式:写日志操做是在write这步完成,而数据文件的写入是在flush这步经过fsync完成。

  • O_DIRECT模式:数据文件的写入操做是直接从mysql innodb buffer到磁盘的,并不用经过操做系统的缓冲,而真正的完成也是在flush这步,日志仍是要通过OS缓冲。

 

经过图能够看出O_DIRECT相比fdatasync的优势是避免了双缓冲,自己innodb buffer pool就是一个缓冲区,不须要再写入到系统的buffer,可是有个缺点是因为是直接写入到磁盘,因此相比fdatasync的顺序读写的效率要低些。

在大量随机写的环境中O_DIRECT要比fdatasync效率更高些,顺序写多的话,仍是默认的fdatasync更高效。

七、innodb_adaptive_flushing 设置为 ON (使刷新脏页更智能)

影响每秒刷新脏页的数目

规则由原来的“大于innodb_max_dirty_pages_pct时刷新100个脏页到磁盘”变为 “经过buf_flush_get_desired_flush_reate函数判断重作日志产生速度肯定须要刷新脏页的最合适数目”,即便脏页比例小于 innodb_max_dirty_pages_pct时也会刷新必定量的脏页。

八、innodb_adaptive_flushing_method 设置为 keep_average

影响checkpoint,更平均的计算调整刷脏页的速度,进行必要的flush.(该变量为mysql衍生版本Percona Server下的一个变量,原生mysql不存在)

九、innodb_stats_on_metadata=OFF

关掉一些访问information_schema库下表而产生的索引统计。

当重启mysql实例后,mysql会随机的io取数据遍历全部的表来取样来统计数据,这个实际使用中用的很少,建议关闭.

十、innodb_change_buffering=all

当更新/插入的非汇集索引的数据所对应的页不在内存中时(对非汇集索引的更新操做一般会带来随机IO),会将其放到一个insert buffer中,当随后页面被读到内存中时,会将这些变化的记录merge到页中。当服务器比较空闲时,后台线程也会作merge操做。

因为主要用到merge的优点来下降io,但对于一些场景并不会对固定的数据进行屡次修改,此处则并不须要把更新/插入操做开启change_buffering,若是开启只是多余占用了buffer_pool的空间和处理能力。这个参数要依据实际业务环境来配置。

十一、innodb_old_blocks_time=1000

使Block在old sublist中停留时间长为1s,不会被转移到new sublist中,避免了Buffer Pool被污染BP能够被认为是一条长链表。被分红young 和 old两个部分,其中old默认占37%的大小(由innodb_old_blocks_pct 配置)。靠近顶端的Page表示最近被访问。靠近尾端的Page表示长时间未被访问。而这两个部分的交汇处成为midpoint。每当有新的Page须要加载到BP时,该page都会被插入到midpoint的位置,并声明为old-page。当old部分的page,被访问到时,该page会被提高到链表的顶端,标识为young。

因为table scan的操做是先load page,而后当即触发一次访问。因此当innodb_old_blocks_time =0 时,会致使table scan所须要的page不读的做为young page被添加到链表顶端。而一些使用较为不频繁的page就会被挤出BP,使得以后的SQL会产生磁盘IO,从而致使响应速度变慢。

这时虽然mysqldump访问的page会不断加载在LRU顶端,可是高频度的热点数据访问会以更快的速度把page再次抢占到LRU顶端。从而致使mysqldump加载入的page会被迅速刷下,并当即被evict(淘汰)。所以,time=0或1000对这种压力环境下的访问不会形成很大影响,由于dump的数据根本抢占不过热点数据。不仅dump,当大数据操做的时候也是如此。

十二、binlog_cache_size

二进制日志缓冲大小:一个事务,在没有提交(uncommitted)的时候,产生的日志,记录到Cache中;等到事务提交(committed)须要提交的时候,则把日志持久化到磁盘。 

设置太大的话,会比较消耗内存资源(Cache本质就是内存),更加须要注意的是:binlog_cache是否是全局的,是按SESSION为单位独享分配的,也就是说当一个线程开始一个事务的时候,Mysql就会为这个SESSION分配一个binlog_cache

怎么判断咱们当前的binlog_cache_size设置的没问题呢? 

mysql> show status like 'binlog_%';                       
+-----------------------+-----------+
| Variable_name         | Value     |
+-----------------------+-----------+
| Binlog_cache_disk_use | 1425      |
| Binlog_cache_use      | 126945718 |
+-----------------------+-----------+
2 rows in set (0.00 sec)

mysql> select @@binlog_cache_size;                        
+---------------------+
| @@binlog_cache_size |
+---------------------+
|             1048576 |
+---------------------+
1 row in set (0.00 sec)

运行状况Binlog_cache_use 表示binlog_cache内存方式被用上了多少次,Binlog_cache_disk_use表示binlog_cache临时文件方式被用上了多少次

1三、innodb_file_per_table

innodb_file_per_table=1

独立表空间

优势:

  • 每一个表的数据和索引都会存在自已的表空间中

  • 能够实现单表在不一样的数据库中移动

  • 空间能够回收(除drop table操做)

  • 删除大量数据后能够经过:alter table TableName engine=innodb;回缩不用的空间

  • 使用turncate table也会使空间收缩

  • 对于使用独立表空间的表,无论怎么删除,表空间的碎片不会太严重的影响性能

缺点:单表增长过大,如超过100个G

结论:共享表空间在Insert操做上少有优点。其它都没独立表空间表现好。当启用独立表空间时,请合理调整一 下:innodb_open_files ,InnoDB Hot Backup(冷备)的表空间cp不会面对不少无用的copy了。并且利用innodb hot backup及表空间的管理命令能够实现单现移动。

1四、增长本地端口,以应对大量链接

echo ‘1024 65000′ > /proc/sys/net/ipv4/ip_local_port_range

该参数指定端口的分配范围,该端口是向外访问的限制。mysql默认监听的3306端口即便有多个请求连接,也不会有影响。可是因为mysql是属于高内存、高cpu、高io应用,不建议把多少应用于mysql混搭在同一台机器上。即便业务量不大,也能够经过下降单台机器的配置,多台机器共存来实现更好。

1五、增长队列的连接数

echo ‘1048576’ > /proc/sys/net/ipv4/tcp_max_syn_backlog

创建连接的队列的数越大越好,可是从另外一个角度想,实际环境中应该使用链接池更合适,避免重复创建连接形成的性能消耗。使用链接池,连接数会从应用层面更可控些。

1六、设置连接超时时间

echo ’10’ > /proc/sys/net/ipv4/tcp_fin_timeout

该参数主要为了下降TIME_WAIT占用的资源时长。尤为针对http短连接的服务端或者mysql不采用链接池效果比较明显。

 

参考文章

http://dev.cmcm.com/archives/107/comment-page-1

http://www.zhdba.com/mysqlops/2012/05/24/mysql-io/

http://blog.itpub.net/22664653/viewspace-1063134/

http://liyangliang.me/posts/2014/03/innodb_flush_log_at_trx_commit-and-sync_binlog/

http://www.cnblogs.com/snifferhu/p/4736479.html

http://www.cnblogs.com/xuanzhi201111/p/4040681.html

http://mysqllover.com/?p=636

相关文章
相关标签/搜索