mysqlinsert超慢_MySQL简单INSERT超慢原因排查
2、profile展⽰:
实际上这⾥的query end是⼀个⾮常有⽤的信息,基本确认是在order_commit函数上的等待。
⼆、问题初次分析
在我遇到的案例中有⼤事务造成的⼩事务commit慢的情况,且状态也是query end,但是这⾥问题显然
不太⼀样,如果是⼤事务造成的会是偶尔出现commit慢的情况⽽这⾥是稳定出现等待1秒的情况。但是我还是要朋友采集了binlog的⼤事务信息使⽤我的⼀个⼯具如下:
这个⼯具是我⽤C写的不依赖其他⼯具解析binlog获取有⽤信息的⼯具,也很多朋友在⽤。占时没有开源,其实也很简单就是分析binlog的event来获取有⽤信息。
得到的简化结果如下:
-------------Now begin-------------- Check Mysql Version is:5.7.19-log Check Mysql binlog format ver is:V4 Warning:Check This binlog is not closed! Check This binlog total size:87546667(bytes) Note:lo
ad data infile not check! -------------Total now-------------- Trx total[counts]:42771 Event total[counts]:251792 Max trx event size:9268(bytes) Pos:78378238[0X4ABF4FE]
Avg binlog size(/sec):16745.729(bytes)[16.353(kb)] Avg binlog size(/min):1004743.688(bytes)[981.195(kb)] ... --Large than 2000000(bytes) trx: (1)Trx_size:54586527(bytes)[53307.156(kb)] trx_begin_p:359790[0X57D6E]
trx_end_p:54946317[0X3466A0D] Total large trx count size(kb):#53307.156(kb) .... ---(79)Current
Table:froad_cbank_anhui.cb_sms_log:: Insert:binlog size(824224(Bytes)) times(3135) Update:binlog size(2046042(Bytes)) times(3841) Delete:binlog size(0(Bytes)) times(0) Total:binlog size(2870266(Bytes)) times(6976) ---(80)Current
Table:test.2018products:: Insert:binlog size(54586359(Bytes)) times(6647) Update:binlog size(0(Bytes)) times(0)
Delete:binlog size(0(Bytes)) times(0) Total:binlog size(54586359(Bytes)) times(6647) ---Total binlog dml event
size:73212228(Bytes) times(65090)
实际上我们很容易看到binlog整个才80M左右确实包含⼀个⼤事务如下,⼤约占⽤了50M多。
--Large than 2000000(bytes) trx: (1)Trx_size:54586527(bytes)[53307.156(kb)] trx_begin_p:359790[0X57D6E]
trx_end_p:54946317[0X3466A0D] Total large trx count size(kb):#53307.156(kb)
我们先排除⼤事务导致的的问题。那么到底是什么问题呢,有朋友说可能是半同步,但是不使⽤半同步的情况下也⼀样。且我觉得半同步的导致慢的状态应该不是query end 占时没有测试。
三、确认问题
没有办法只能使⽤pstack进⾏分析,幸运的是这个问题确实简单如下的pstack栈帧:
显然我的猜测没有问题确实是ordered_commit上出的问题,直接打开源码到如下:
这段代码位于flush阶段之后 sync阶段之前,⽬的在于通过⼈为的设置delay来加⼤整个group commit组的事务数量,从⽽减少进⾏磁盘刷盘sync的次数。这块代码虽然以前看过但是没⽤过这两个参数也就直接跳过了。
四、stage_manager.wait_count_or_timeout函数分析和参数分析
这个函数还是⾮常简单如下逻辑 看注释即可:
void Stage_manager::wait_count_or_timeout(ulong count, ulong usec, StageID stage) { ulong to_wait=
DBUG_EVALUATE_IF("bgc_set_infinite_delay", LONG_MAX, usec); /* For testing purposes while waiting for inifinity to arrive, we keep checking the queue size at regular, small intervals. Otherwise, waiting 0.1 * infinite is too long. */ ulong delta= DBUG_EVALUATE_IF("bgc_set_infinite_delay", 100000, //此处将等待时间分割 将使⽤ max(1, (to_wait * 0.1)));
//binlog_group_commit_sync_delay*0.1 和 1之间的 ⼤的那个值作为时间分割 (单位 1/1000000 秒)
//binlog_group_commit_sync_delay是 (1000000)1秒则时间分割为0.1s(100000) while (to_wait > 0 && (count == 0 ||
static_cast(m_queue[stage].get_size()) < count)) //进⾏主体循环退出条件为 1、binlog_group_commit_sync_delay设置的时间消耗完 { //2本组事务数量>binlog_group_commit_sync_no_delay_count my_sleep(delta);//每次休眠delta时间如果是1秒则每次休眠0.1秒 to_wait -= delta;//进⾏总时间-delta 时间 } }
从源码我们分析⼀下参数binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count的含义:
binlog_group_commit_sync_delay:通过⼈为的设置delay来加⼤整个group commit组的事务数量,从⽽减少进⾏磁盘刷盘sync的次数,但是受到binlog_group_commit_sync_no_delay_count的限制,单位1/1000000秒。最⼤值1000000也就是1秒
binlog_group_commit_sync_no_delay_count:如果delay的时间内如果group commit中的事务数量达到了这个设置就直接跳出等待,⽽不需要等待binlog_group_commit_sync_delay的时间,单位group commit中事务的数量。
mysql下载后的初次使用
举个列⼦⽐如我binlog_group_commit_sync_delay设置为10,binlog_group_commit_sync_no_delay_count设置为10,整个group commit将在这⾥等待,达到2个条件中的1个将会退出等待:
等待达到了1/100000 秒
group commit中事务数量达到了10
最后叫朋友查看了他们库的设置如下:
居然binlog_group_commit_sync_delay设置为了最⼤值1000000也就是1秒,这也就解释了为什么简单的insert都会等待1秒了,且状态为query end。
五、总结
整个问题的排除最终还是依赖的pstack,这也再⼀次体现了它的重要性。栈帧是不会骗⼈的只有不懂的
要对query end代表的什么⽐较清楚
⾄此我知道了2种query end(或者显⽰commit为starting)状态下⼩事务提交慢的可能 1、某个⼤事务提交引起偶尔的提交慢 2、
binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count 设置不正确引起提交慢

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。