MySQL 写数据 IO参数汇总

MySQL 参数

MySQL Innodb 专用参数:

使用到的测试脚本

在这里我还是使用我之前的python脚本,可以用来模拟并发和自动生成INSERT语句.

下载地址: https://github.com/jackey/MySQLTools

Clone下来后,复制default.config.ini 命名为config.ini 然后输入对应的参数; 创建测试数据库和测试表, 参考 这里

然后运行:

./bin/io_test

重要参数:

consume: 并发用户个数
count: 每个consume产生的SQL个数

这个脚本还没有开源,入手也比较难,如果有问题可以随时找我. 然后测试的表也是innodb,后面的优化都是基于innodb引擎.

目前瓶颈和优化目标

优化过程

第一次测试:

测试变量:

consume: 1
count: 10000 (1万个插入SQL)

测试结果:

Start Running at: 2013-09-23 15:14:39.606895
Start Consume with name: Thread-1.
Finished at: 2013-09-23 15:25:20.730606

可以看到一个用户执行1万个插入SQL,竟然需要15mins 41s (忽略毫秒). 这个是一个很严重的性能问题;我们现在要想优化它就要明白MySQL和Innodb做了哪些磁盘IO操作然后通过配置来减少IO操作.

让我们回忆下,下面这些IO操作可能会用到:

我们一个一个的来优化,然后看下效果;


二进制事务写日志:

因为innodb是事务型存储引擎,所以每次都是一个事务,如果设置为autocommit=1,那就会自动的commit查询;每次事务都需要把事务包含的查询写入日志,这里有几个参数涉及到这个功能点:

我现在MySQL配置里面, 配置是这样子的:

innodb_flush_log_at_trx_commit=1 (每次事务提交都需要写入日志, [详情](http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit))
innodb_log_buffer_size=8388608 (近似8MB)
innodb_log_file_size=5242880 (近似5MB)

很显然,innodb_flush_log_at_trx_commit是有优化的可能,因为每次都需要写入日志文件是一个很大的IO开销, 我设置为0,意思是每隔1s写入日志文件.

innodb_flush_log_at_trx_commit=0
innodb_log_buffer_size=8388608
innodb_log_file_size=5242880

其他变量保持不变。重启MySQL然后用同样的测试变量测试一遍,结果如下:

Start Running at: 2013-09-23 16:05:19.719965 
Start Consume with name: Thread-1.
Finished at: 2013-09-23 16:05:40.266169 

天啦,只花了21s, 提升了将近44.8倍的效率! 不过设置为0的负作用是有的,因为不是实时的写入事务日志,所以不算严格意义上的ACID,所以如果发生crash事件(包括innodb 引擎的crash)会丢失最后1s的数据.

然后我们看下是否需要增加log_buffer_size, 这个参数的意义在于如果有一个比较大的事务需要处理,设置这个参数可以让整个事务日志先寄存在buffer里,在完成事务时候再一起刷到磁盘中,在这里我们没有这么大的事务所以不需要设置此值. 然后innodb_log_file_size 这个文件我觉得有必要增加,它的意义在于事务文件的大小,对于innodb来说事务操作无处不在,所以我们需要增加事务文件大小来减少MySQL对日志文件的checkpoint,这样也可以减少IO. 这里有更详细的设置方法

下面是我修改后的配置:

innodb_flush_log_at_trx_commit=0
innodb_log_buffer_size=8388608
innodb_log_file_size=134217728

下面的是测试结果:

Start Running at: 2013-09-23 16:31:15.607059 
Start Consume with name: Thread-1.
Finished at: 2013-09-23 16:31:22.692315

可以看到速度又有一次飞跃,只花了 7s. 提高了3倍! 在这里我加大了 innodb_log_file_size 到 512MB 但是测试下来发现并没有提高性能(多次测试时间大概是7-8s左右 并没有提高),我猜测原因是我的事务不多,100M左右的日志文件应该足够了。


数据写优化

Innodb有一个很重要的参数就是 innodb_buffer_pool_size, 它缓存了索引和数据在内存里面,默认大小是128MB. 我增加到1GB试试.

innodb_buffer_pool_size=1G

不过测试下来结果且不满意,如下:

Start Running at: 2013-09-23 17:06:41.078170
Start Consume with name: Thread-1.
Finished at: 2013-09-23 17:06:48.263859

性能并没有提高;查看了下 innodb status 发现buffer pool还很充足:

Free buffers: 107963

这里我猜测innodb_buffer_pool_size已经满足了需求,增太大也没有意义。不过MySQL官方文档强调,这个变量对innodb引擎性能影响非常大,可以有效减少IO.

继续尝试,仔细思考下, 1W个insert操作都不并发请求,所以和MySQL应该不会创建

总结