MySQL写压力性能监控与调优

1、关于DB的写

一、数据库是一个写频繁的系统
二、后台写、写缓存
三、commit须要写入
四、写缓存失效或者写满-->写压力陡增-->写占读的带宽
  一、BBU失效
  二、写入忽然增长、cache满
五、日志写入、脏缓冲区写入mysql

 
2、写压力性能监控
  全面剖析写压力:多维度的对写性能进行监控。
一、OS层面的监控:iostat -x
[root@localhost mydata]# iostat -x
Linux 2.6.32-642.el6.x86_64 (localhost.chinaitsoft.com)     07/05/2017     _x86_64_    (8 CPU)
 
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.03    0.00    0.00   99.97
 
Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.01     0.00     7.72     0.00    1.25    1.25    0.00   1.25   0.00
sdc               0.02     0.00    0.01    0.00     0.07     0.00     7.93     0.00    0.89    0.89    0.00   0.72   0.00
sda               0.18     0.13    0.13    0.05     5.38     1.43    37.95     0.00    6.63    3.99   13.77   2.23   0.04
sdb               0.03     0.00    0.01    0.00     0.12     0.00     8.72     0.00    1.14    0.80   35.89   0.71   0.00
  一、写入的吞吐量:wsec/s  sec=512字节=0.5K、 写入的响应时间:await
  二、咱们须要确认咱们的系统是写入仍是读取的系统,若是是写入为主的系统,写压力天然就大,相关状态值也就大些。
  三、监控系统的io情况,主要查看%util、r/s、w/s,通常繁忙度在70%,每秒写也在理想值了;但若是系统目前繁忙度低,每秒写很低,能够增长写入。
二、DB层面监控,有没有写异常:监控各类pending(挂起)
mysql> show global status like '%pend%';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| Innodb_data_pending_fsyncs   | 0     |     #被挂起的fsync
| Innodb_data_pending_reads    | 0     |     #被挂起的物理读
| Innodb_data_pending_writes   | 0     |     #被挂起的写
| Innodb_os_log_pending_fsyncs | 0     |     #被挂起的日志fsync
| Innodb_os_log_pending_writes | 0     |     #被挂起的日志写
+------------------------------+-------+
5 rows in set (0.01 sec)
  写挂起次数值大于0,甭管是什么写挂起,出现挂起的话就说明出现写压力,因此值最好的是保持为0。监控“挂起”状态值,出现大于0且持续增长,报警处理。
三、写入速度监控:日志写、脏页写
  一、日志写入速度监控
mysql> show global status like '%log%written';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Innodb_os_log_written | 5120  |
+-----------------------+-------+
1 row in set (0.01 sec)
  二、脏页写入速度监控
mysql> show global status like '%a%written';
+----------------------------+---------+
| Variable_name              | Value   |
+----------------------------+---------+
| Innodb_data_written        | 1073152 |     #目前为止写的总的数据量,单位字节
| Innodb_dblwr_pages_written | 7       |
| Innodb_pages_written       | 58      |     #写数据页的数量
+----------------------------+---------+
3 rows in set (0.01 sec)
  三、关注比值Innodb_dblwr_pages_written / Innodb_dblwr_writes,表示一次写了多少页
mysql> show global status like '%dblwr%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 7     |     #已经写入到doublewrite buffer的页的数量
| Innodb_dblwr_writes        | 3     |     #doublewrite写的次数
+----------------------------+-------+
2 rows in set (0.00 sec)
    一、若是该比值是64:1,说明doublewrite每次都是满写,写的压力很大。
    二、若是系统的double_write比较高的话,iostat看到的wrqm/s(每秒合并写的值)就高,由于double_write高意味着每次写基本上都是写2M,这时候就发生更多的合并,但wrqm/s高并不惧怕,由于发生合并是好事,看wrqm/s和繁忙度能不能接受。 
四、脏页的量监控
mysql> show global status like '%dirty%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| Innodb_buffer_pool_pages_dirty | 0     |     #当前buffer pool中脏页的数量
| Innodb_buffer_pool_bytes_dirty | 0     |     #当前buffer pool中脏页的总字节数
+--------------------------------+-------+
2 rows in set (0.01 sec)
 
mysql> show global status like 'i%total%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| Innodb_buffer_pool_pages_total | 8192  |     #buffer pool中数据页总量
+--------------------------------+-------+
1 row in set (0.01 sec)
  关注比值Innodb_buffer_pool_pages_dirty / Innodb_buffer_pool_pages_total,脏页占比
  经过比值看脏页是否多,好比脏页10%的话,能够判断系统可能不是写为主的系统。
五、写性能瓶颈
mysql> show global status like '%t_free';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| Innodb_buffer_pool_wait_free | 0     |
+------------------------------+-------+
1 row in set (0.01 sec)
 
mysql> show global status like '%g_waits';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_log_waits | 0     |
+------------------+-------+
1 row in set (0.00 sec)
  一、Innodb_buffer_pool_wait_free,若是该值大于0,说明buffer pool中已经没有可用页,等待后台往回刷脏页,腾出可用数据页,这样就很影响业务了,hang住。
  二、Innodb_log_waits,若是该值大于0,说明写压力很大,出现了日志等待。
六、系统真实负载:rows增删改查 、事务提交、事务回滚
mysql> show global status like 'i%rows%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Innodb_rows_deleted  | 0     |
| Innodb_rows_inserted | 145   |
| Innodb_rows_read     | 233   |
| Innodb_rows_updated  | 5     |
+----------------------+-------+
4 rows in set (0.01 sec)
 
mysql> show global status like '%commit%';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| Com_commit     | 0     |
| Com_xa_commit  | 0     |
| Handler_commit | 16    |
+----------------+-------+
3 rows in set (0.01 sec)
 
mysql> show global status like '%rollback%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Com_rollback               | 0     |
| Com_rollback_to_savepoint  | 0     |
| Com_xa_rollback            | 0     |
| Handler_rollback           | 0     |
| Handler_savepoint_rollback | 0     |
+----------------------------+-------+
5 rows in set (0.01 sec)
  经过监控系统真实负载,若是业务正常,负载上升,写压力是那天然是无可厚非的。此时,就要根据业务具体状况,进行相应的调优。 
 
3、写压力调优参数
  下降写压力、加大写入的力度。
  经过调整参数下降写压力时,必定要实时关注iostat系统的各项指标。
一、脏页刷新的频率
mysql> show variables like 'i%depth%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_lru_scan_depth | 1024  |
+-----------------------+-------+
1 row in set (0.01 sec)
  默认1024,遍历lru list刷新脏页,值越大,说明刷脏页频率越高。
二、磁盘刷新脏页的量磁盘io能力
mysql> show variables like '%io_c%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_io_capacity     | 200   |
| innodb_io_capacity_max | 2000  |
+------------------------+-------+
2 rows in set (0.00 sec)
  根据磁盘io能力进行调整,值越大,每次刷脏页的量越大。
三、redolog调优
mysql> show variables like 'innodb_log%';
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| innodb_log_buffer_size      | 16777216 |
| innodb_log_checksums        | ON       |     #解决数据在io环节的出错问题,checksum值检查
| innodb_log_compressed_pages | ON       |
| innodb_log_file_size        | 50331648 |
| innodb_log_files_in_group   | 2        |
| innodb_log_group_home_dir   | ./       |
| innodb_log_write_ahead_size | 8192     |
+-----------------------------+----------+
7 rows in set (0.01 sec)
  logfile大小和组数可能会致使写抖动:日志切换频率须要监控(文件系统层面技巧)。
四、redolog的刷新机制
mysql> show variables like '%flush%commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.00 sec)
  默认MySQL的刷盘策略是1,最安全的,可是安全的同时,天然也就会带来必定的性能压力。在写压力巨大的状况下,根据具体的业务场景,牺牲安全性的将其调为0或2。
关于redolog的刷盘策略:
  也就是用户在commit,事务提交时,处理redolog的方式(0、一、2):
  0:当提交事务时,并不将事务的redo log写入logfile中,而是等待master thread每秒的刷新redo log。(数据库崩溃丢失数据,丢一秒钟的事务)
  1:执行commit时将redo log同步写到磁盘logfile中,即伴有fsync的调用(默认是1,保证不丢失事务)
  2:在每一个提交,日志缓冲被写到文件系统缓存,但不是写到磁盘的刷新(数据库宕机而操做系统及服务器并无宕机,当恢复时能保证数据不丢失;可是文件系统(OS)崩溃会丢失数据)
五、定义每第二天志刷新的时间
mysql> show variables like 'innodb_flush_log_at_timeout';
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| innodb_flush_log_at_timeout | 1     |
+-----------------------------+-------+
1 row in set (0.01 sec)
  默认是1,也就是每秒log刷盘,配合innodb_flush_log_at_trx_commit来设置,为了充分保证数据的一致性,通常innodb_flush_log_at_trx_commit=1,这样的话,innodb_flush_log_at_timeout的设置也就没有意义了。所以,该参数的设置只针对innodb_flush_log_at_trx_commit为0/2起做用。
六、内存脏页占比控制
mysql> show variables like '%dirty%pct%';
+--------------------------------+-----------+
| Variable_name                  | Value     |
+--------------------------------+-----------+
| innodb_max_dirty_pages_pct     | 75.000000 |     #脏页在buffer pool中的最大占比
| innodb_max_dirty_pages_pct_lwm | 0.000000  |
+--------------------------------+-----------+
2 rows in set (0.01 sec)

  在内存buffer pool空间容许的范围下,能够调大脏页容许在内存空间的占比,可解燃眉之急,下降写压力。ios

七、关闭doublewrite下降写压力
mysql> show variables like '%doub%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+
1 row in set (0.01 sec)
  两次写特性,默认开启,静态参数。关闭doublewrite适合的场景:
  一、海量DML
  二、不害怕数据损坏和丢失
  三、系统写负载成为主要负载,关闭doublewrite,下降写压力
注意:
  关于参数调整的生效范围,如何调整(静态参数、动态参数),都是要依据官方文档,依照文档进行调参。
相关文章
相关标签/搜索