MySQL系列(12): MyISAM 锁机制详解

  MyISAM存储引擎只支持表级锁。该锁类型是也使用非常广泛的锁类型。

获取表锁争用情况

通过检查Table_locks_immediateTable_locks_waited状态变量来分析系统上的表锁定争夺:

1
SHOW STATUS LIKE 'table%';

如果Table_locks_waited值比较高,说明存在较严重的表级锁争用情况。

表级锁的锁模式

MySQL 表级锁有两种锁模式:表共享读锁(Table Read Lock)和表独占锁(Table Write Lock)

  1. 表共享读锁(Table Read Lock)
    不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求。加锁如下:
    1
    LOCK TABLE tb_name READ;
  2. 表独占锁(Table Write Lock)
    会阻塞其他用户对同一表的读和写操作。加锁如下:
    1
    LOCK TABLE tb_name WRITE;

解锁:,表锁是数据库服务器提供的,解锁针对的是当前事务涉及的所有加锁的表。

1
UNLOCK TABLES;

MyISAM 表的读操作与写操作之间,以及写操作之间是串行的。当一个线程获取对一个表的写锁后,只有持有锁的线程可以对表进行更新操作,其它线程的读、写操作都会等待,直到锁被释放为止。

加表锁

  MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁;在执行更新操作(update,delete,insert等)前,会自动给涉及的表加写锁

  用户一般不需直接用LOCK TABLE命令给MyISAM表显示式加锁。显式加锁一般是在涉及多个表数据一致性时使用,如校对订单表的总额和订单明细表每一件商品小总额,这涉及两张表,为防止一张表被改变,可以先给两张表加锁。

  在执行LOCK TABLES后,只能访问显示加锁的表,不能访问未加锁的表;如果加的是读锁,只能执行查询操作,不能执行更新操作。MyISAM 自动加锁也是如此。MyISAM 是一次获得 SQL 语句所需要的全部锁。这也是MyISAM不会出现死锁的原因。

  当使用LOCK TABLES时,会一次锁定用到的所有表,如果一个表在SQL中出现多次,则需要使用别名并对别名进行锁定。

1
2
-- 表别名也加锁
LOCK TABLE tb_name t1 READ, tb_name t2 READ;

并发插入

MyISAM 表的读和写是串行的。但在一定条件下,MyISAM 表也支持查询和插入操作的并发进行。

MyISAM 引擎有一个系统变量concurrent_insert,专门用以控制并发插入的行为。

  1. concurrent_insert设置为0时,不允许并发插入。
  2. concurrent_insert设置为1时,如果 MyISAM 表中没有空洞(即表中间没有被删除的行),允许一个进程读表的时间,另一个进行从表尾插入记录。
  3. concurrent_insert设置为2时,无论 MyISAM 表有没有空洞,都允许在表尾并发插入记录。

该并发插入特性用来解决应用中对同一表查询和插入的锁争用。

1
2
3
4
5
-- 设置是否开启并发insert,0=不开启,1=没有空洞的情况下,允许insert,2=不管有没有空洞,都允许插入  
set global concurrent_insert=2;

-- 使用并发插入锁,在读的属部增加`LOCAL`选项
LOCK TABLE tb_name READ LOCAL;

MySQL系列(12): MyISAM 锁机制详解

http://blog.gxitsky.com/2019/02/24/MySQL-12-lock-MyISAM/

作者

光星

发布于

2019-02-24

更新于

2023-03-06

许可协议

评论