如果进行很小的查询也导致长时间的阻塞问题,就需要我们进行一些好好的分析了

比如说,一个如下的语句

select * fron t where id =1 ;

1.这种长时间不进行返回的情况,大概率是因为整个表被锁住了,可以考虑使用show processlist指令查看语句状态

图片

常见的这种阻塞就是有人持有一个MDL写锁,导致select被阻塞了

图片

sessionA长期持有表t的MDL写锁,

这种情况可以考虑通过show processlist来查看并杀死进程,或者通过sys.schema_table_lock_waits这个表,查询造成阻塞的process id,进行kill即可

2.等待flush

可能出现的一种极端情况,就是在进行flush table的时候,发生了阻塞,导致的问题出现

首先是flush操作

flush tables t with read-lock;

flush tables with read lock;

情况如下:

图片

执行上面的流程的时候,session A导致了这个表被长期锁住了

sessionB 的刷新操作无法正常执行,导致了SessionC的无法执行

3.行级锁的等待

select *from t where id = 1 lock in share mode;

如果这一行已经被锁住了,那么可能会导致select 语句被堵住了

图片

这种情况不必说,SessionA启动了事务之后没有提交,导致了SessionB被堵住了,

如何解决的这个问题呢,可以通过

SELECT * FROM sys.`innodb_lock_waits` WHERE locked_table = ‘test.a’

然后使用kill命令进行杀死进程即可

4.极端情况

开启一个事务,但是在开启之前,进行插入了10万行数据,例如如下

然后另一个事务进行了更新10次

图片

然后进行查询这一个被更新100万次的数据

使用了lock in share mode的一行,使用了当前读,导致快,直接返回当前数据

但是select * from t where id =1; 是一致性读,导致需要用undo log进行100万次的回滚,才能取到最后结果

5.查询不符合问题

mysql> CREATE TABLE `table_a` (

`id` int(11) NOT NULL,

`b` varchar(10) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `b` (`b`)

) ENGINE=InnoDB;

表里有10万行数据,多数为1234567890

然后进行一次查询

select * from table_a where b=’1234567890abcd’

这时候server层直接进行发送sql给引擎层,但是引擎层会将数据截断,保留前10个

进行匹配的时候,满足1234567890的数据不少,因为select * 会进行多次回表

回表后又发现不匹配1234567890abcd,于是干了多次白活

发表评论

邮箱地址不会被公开。 必填项已用*标注