首页 > 数据库 > 数据库开发技术 > MySQL:慢查询引起的故障和疑问等4例
简单记录,仅供参考。


5.7.22版本
大概问题就是,数据库crash 过后,有一个线程CPU很高,执行show processlist等语句,都是第一次可以执行,而第二次就不能执行了,等待如下。

其他线程CPU不高。
对于类似问题,很显然是耗用CPU的线程正在处理某种工作,这种工作可能到堵塞了其他session。这种场景适合用pstack进行分析,因为反正都卡住了,也无所谓。
当然PSTACK,很容易就看出了在干什么如下:
耗用CPU的线程:这个线程记录慢查询到slow_log,发现需要修复,正在对slow_log 这个表进行修复,具体是CSV引擎,我也不过多关注了,栈如下:
其他等待的线程:
其他session如果也想记录slow_log,那么需要先open 表获取MDL LOCK。很显然由于正在对slow_log进行修复,这个过程可能由于slow_log巨大而非常慢,这个过程持有了MDL LOCK(独占),因此出现waiting for table metadata lock的等待,这也是正常的。
上面我们看到了执行语句第一次是可以执行的,只是第二次卡住了。这个问题主要是,记录慢查询的时候,实际上语句已经执行完成了,并且客户端已经接收到了Result Set报文,客户端看来语句执行结束了,但是这个session(线程)还在跑记录慢查询接口,实际上已经卡主了。
当再次客户端发送COM_QUERY 报文给MySQLD的时候,当然这个线程就不能读取到命令。
上面的show processlist虽然显示等待为waiting for table metadata lock,但是这个等待是等待在slow_log这个table上的,查询的结果已经发送结果给客户端了。
大概就是这个意思,如下:
服务端线程 客户端
发起查询请求
接收客户端语句
执行语句
发送结果给客户端
获取结果语句结束
记录慢查询堵塞(MDL LOCK)
再次执行语句
无法响应
这个小案例也说明,我们还是不要使用表来记录慢查询吧。
当我们使用mysqldump --master-data > sql.sql 这种方式备份的时候,在8.0.26和8.0.28之前有一个小BUG,就是master-data 已经成为了警告,需要使用source-data进行代替,如果不代替,出现的警告会写入到stdout中,然后被重定向到sql.sql中。当然一般的错误和警告还是写到stderr。
当进行恢复的时候就会出现报错,这个小BUG在8.0.30进行了修复如下:
Deprecation warnings returned to client programs were sent to stdout rather than stderr, which in the case of mysqldump could mean that the dump file no longer worked because the warnings were included in it. The issue has now been fixed and the warnings are sent to stderr. (Bug #104769, Bug #33733529)
所以如果是这几个版本最好用source-data来代替master-data,避免恢复数据报错。
很早以前就注意过这个SUM_LOCK_TIME,当时测试没啥用,就没管了,最近稍微看了一下,为什么没用。如下。
来自于2个函数
慢查询记录lock time时候使用
(A+B)- start_time:因此一般lock time包含了MDL LOCK和row lock的时间,当然不完全相等,因为A是一个流程值。
和lock time的不同在于其只包含了A,也就是时间是 A - start_time,也就是去掉引擎层的等待时间,innodb就是row lock,其来源也是THD::set_time_after_lock打开看就明白了。
mysql_lock_tables
->THD::set_time_after_lock
->pfs_set_statement_lock_time_v2
->inline_mysql_set_statement_lock_time
在MySQL 8.0中出现了很多的迭代器,比如:
当然还有很多很多的迭代器,它们有一个统一的父类RowIterator,比如FilterIterator迭代器,
最近在找where条件过滤的时候,我去找了一阵子,比如如下语句:
select * from tab where a=1;
如果走全表扫描实际上就是FilterIterator迭代器套TableRowIterator迭代器,先通过全表扫描,拿到一行数据,然后通过FilterIterator去过滤这个where条件。这个和5.7完全不同了。大概就是这个意思,
而5.7的where条件过滤是这样的:
很是不一样,统一的抽象更加标准化了,不能说不同,那是完全不同啊。这部分还需要学习。
原文作者:MySQL学习;如有侵权,请联系管理员删除。