美文网首页
MySQL-MyISAM表锁引起慢查询

MySQL-MyISAM表锁引起慢查询

作者: 8813d76fee36 | 来源:发表于2018-05-16 14:04 被阅读491次

场景

模拟并发场景下,其中一个会话在执行更新表操作,同时另一个会话执行查询操作。该查询操作本身很简单,查询的数据量也很小,但是查询速度很慢。

场景复原

模拟更新操作导致锁表

假设我们有一张商品信息表t_good_info,现在更新ID为1的商品价格price
这里使用sleep(N)函数来模拟耗时操作。

在session1中执行:

update t_good_info set price = sleep(20) where id = 1;

正在执行更新

执行查询

假设另一个用户此时查询商品信息,如查询id为2的商品信息。

select * from t_good_info where id = 2;

查询操作被阻塞
查询一条数据耗时28秒!

从途中看到,仅仅一条查询就耗时28秒!

问题排查

  • 首先先查看一下MySQL的进程状态

show processlist;

查询操作等待表级锁

从图中看到查询操作被阻塞,状态显示其正在等待表级锁。

  • 查看表引擎
    由于在写操作时出现了表锁,因此查看该表的存储引擎是否是MyISAM。

show create table t_good_info;

查看表结构
ENGINE字段可以看出该表使用的是MyISAM。

MyISAM 与表锁

MyISAM存储引擎采用的锁是表级锁,表级锁有以下特点:
开销小,粒度大,不易出现死锁,锁竞争概率大,并发效果差。

  • 查看表级锁争用情况

show status like 'table%';

查询表级锁争用情况

table_locks_waited数值越大,则表级锁争用越严重。

  • 表级锁的两种模式
    表级锁有两种体现:读锁、写锁。其表现形式也类似Java中的读写锁。
    如果表加上读锁,则其他对该表的读操作可以并行执行,但写操作会被阻塞;如果是写锁,则对该表的读、写操作都会串行执行。

MyISAM 表级锁(读写锁)效果演示

  • 读锁
    先手动给表t_good_info加上读锁。

lock table t_good_info read;

读锁
开启两个会话查询t_good_info表,发现可以并行执行。 session1
session2

此时尝试做写操作,发现写操作被阻塞。

写操作被阻塞
写操作被阻塞2

释放读锁

unlock tables;

释放读锁

此时被阻塞的写操作得到执行。可以看到该插入操作执行时间为54秒,期间正是在等待读锁释放。


写操作执行
  • 写锁
    写锁会在表执行写操作时自动加锁,引起查询阻塞,表现形式即本文场景中提到的情况。

解决方案

  • 不使用MyISAM引擎
    MySQL 8.0中已经去除MyISAM引擎的表,也表明MySQL已不建议使用该引擎。
  • 在读操作远频繁于写操作时使用
    由于表锁开销小,在读操作使用频率远远大于写操作的场景下依然可以使用MyISAM引擎。

相关文章

网友评论

      本文标题:MySQL-MyISAM表锁引起慢查询

      本文链接:https://www.haomeiwen.com/subject/yqhpdftx.html