如果进行很小的查询也导致长时间的阻塞问题,就需要我们进行一些好好的分析了
比如说,一个如下的语句
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,于是干了多次白活