在大量的客户端,更新数据表的同一行时,会造成数据库的吞吐量大幅降低。
很多数据库的前辈和同行分别通过实验和源码的方法,定位到了罪魁祸首----MySQL死锁检测
实验方式:http://blog.csdn.net/zhaiwx1987/article/details/6952285
源码方式:http://www.gpfeng.com/?p=426
请大家尤其注意这段代码
#####
lock_mutex_enter();
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
block, heap_no, index, thr);
MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
lock_mutex_exit();
#####
可以看出,MySQL在试图获取锁期间,会有lock_mutex_enter 和lock_mutex_exit保护。
在一般情况下,lock_rec_lock执行速度很快,所以不成问题。
但是如果有大量锁等待的情况,比如多个客户端试图更新同一行,则这个过程非常缓慢。因此整个innodb层就由并行变成了串行,大幅降低TPS。
解决办法:
让锁等待尽量少,可以通过在数据库层设置等待队列达到这个效果,而OneSQL内置了这个方案。
测试用例:
update miaosha set mount=mount+1 where id=1;
测试环境
MySQL和OneSQL的关键参数配置如下,且均未开启binlog
数据库 | innodb_flush_log_at_trx_commit | innodb_log_file_size | innodb_buffer_pool_size |
OneSQL | 1 | 1000M | 8G |
MySQL | 1 | 1000M | 8G |
硬件环境
内存 | cpu | 磁盘 |
32g | 8c 每个core上有两个超线程 Intel(R) Xeon(R) CPU E5620 @ 2.40GHz |
2块raid0 7500r |
测试结果:
在512个线程情况下,TPS为500/s
我实际测试,同样的环境下使用OneSQL,TPS可以达到15682/s,性能提升达30倍左右。
如有任何疑问,请联系微信onesoft007