Quirk Quest|Mysql单个库表死锁问题

156 阅读6分钟

前言

妈呀,吓死了都,一个早上都没好过。还好是测试环境的数据库,还好是主备数据。可恶啊,今天,在操作库表的时候,像备份一张1.8G的表数据,备份完毕,修改了一下表的名称。这时候就裂开,那张表一直在响应中,我看它操作太久了,像关闭但是它好像要跟我作对一样,死活不关闭,页面一直是响应中。我记得强制关闭,结果出现了问题,测试环境的项目连接数据库出现线程不足的错误。我便开始解决这个问题。

解决

出现了这个问题,但是主的数据库又不算出现很大问题,应该只有一张表无法进行操作,或者说是长时间响应。此时,我便修复了项目指向的数据库,直接指向备用数据,重启。让测试项目的项目先运行起来。在看看,主数据的问题。

接着,我在服务器查看mysql的cpu 和内存的使用率,简单的top命令了一下,发现mysql的cpu使用高达400%,看来真的烧坏了。看到这里,我就怀疑数据库是不是在执行什么长时间的查询。但是,不应该,在备份之前数据库都是正常进行,而且稳定的运行。总不能是修改库表的名称导致的吧。

这时候,我感觉是不是有查询延迟了。那就上控制台使用 SHOW PROCESSLIST;命令看看

使用以下命令查找与该表相关的数据库进程:

SHOW PROCESSLIST;

这将列出当前数据库中的所有活动进程。查找与该表相关的进程,通常可以通过查看进程的"Info"列来确定正在执行的SQL语句。

发现state字段那一列有很多的 Waiting for table metadata lock

"Waiting for table metadata lock"表示某个操作正在等待对表的元数据锁定,可能是由于其他操作正在修改表的结构或元数据而导致的阻塞。

并且查看 info发现在这些死锁的进行都是查询无法操作的那张表看到这里,我觉得这不是很简单了,这些把这些阻塞的进程杀掉就好辣。分分钟解决。

不过,现在有一个问题就是多100多个这样的查询,我一个一个手动删除不是很蠢?拜托,拜托,浪费时间的事情,少做点,来写一个查询吧:

用于查找并生成终止命令

SELECT CONCAT('KILL ', id, ';') AS KillStatement
FROM information_schema.processlist
WHERE state = 'Waiting for table metadata lock';

ok,ok 把结果集复制出来,执行一下,哦耶,美滋滋。这样就可以了。

当我在重新使用navicat连接那张表,还是出现了长时间的响应等待。在上去执行SHOW PROCESSLIST;命令发现又出现不一样的state:Waiting for table flush state

"Waiting for table flush state"是MySQL中的一个状态,表示正在等待将表的数据从内存中刷新到磁盘上的持久存储区域。当执行写入操作(如插入、更新或删除)时,MySQL会将数据先写入内存中的缓冲区,然后定期将缓冲区中的数据刷新到磁盘上的表文件中。

可恶,不是吧,不是吧;我就当你需要重新读取,我等,我忍。过了一段时间,呃呃,有出现了最开始的错误Waiting for table metadata lock还是那张表的查询导致的。哇,我立即就急了,怎么回事啊,没效果嘛?不对,不对,我在执行SHOW PROCESSLIST;注意到来一个checking permissions状态

"checking permissions" 是 MySQL 连接的一个状态,表示正在检查用户权限。通常情况下,这个状态不应该持续很久,因为权限检查应该是相对快速的操作。

如果发现某个连接的状态一直处于 "checking permissions",并且持续时间过长,可能存在某种问题导致权限检查被阻塞或延迟。在这种情况下,可以尝试通过杀死该连接来解决问题。

发现它在我执行以上操作的时候一直都在,我就在想是不是它导致的?可是,我没有执行什么相关的操作啊。不过,它很可疑还是杀掉试试。

SELECT CONCAT('KILL ', id, ';') AS KillStatement
FROM information_schema.processlist
WHERE state = 'checking permissions';

运行命令,获取结果集执行。然后,到服务上执行top命令发现cpu使用率变到22%,哇,那就是它干的坏事。

科普时间:

为什么会出现checking permissions的状态语句?

"Checking permissions" 是 MySQL 数据库中的一个状态,它表示正在进行权限检查操作。在执行查询或修改操作之前,MySQL 会检查当前用户对数据库对象(例如表、视图、函数)的权限是否足够,以确保用户有权进行相应的操作。

当您执行某个查询或修改语句时,MySQL 会先进行权限检查,验证当前用户是否具有执行该操作的权限。这个过程可能涉及到检查用户的权限配置、角色授权、表级权限等内容。

那看来,是我在修复表名称的时候,它在查询是否有修复权限的时候导致堵塞了。又或者是我在修改表名称的时候,刚好有别的查询在查询这个表导致的。不过这些都不好说。

总结

看来对mysql数据库还是停留在使用上面,虽然增删改查都会了。但是,遇到这样的问题还是有点害怕。看来还需要更深入了解一下Mysql。不过,这些以后再说咯。

话说回来了,我突然记起一些sql注入攻击好像就会注入一些让查询语句让查询变慢。导致sql语句出现问题。

我记起来,那再多说一些,有些接口可以通过延时注入的方式进行攻击。

例如:

'and(select*from(select+sleep(10))a/**/union/**/select+1)='

通过构造这样的sql语句就可以,让该条查询的进行休眠。

我当时复现修复漏洞的时候,使用SHOW PROCESSLIST;就发现 那条sql查询变得十分的旧,一直在请求,等待数据返回。至于危害嘛,懂得都懂、不懂说了也不懂。🐕

eg:

SELECT  * from XXX where 1=1 and (select*from(select+sleep(30))a/**/union/**/select+1)

image-20230608164812147.png

image-20230608165015011.png