MySQL系列(12): MyISAM 锁机制详解
MyISAM存储引擎只支持表级锁。该锁类型是也使用非常广泛的锁类型。
获取表锁争用情况
通过检查Table_locks_immediate
和Table_locks_waited
状态变量来分析系统上的表锁定争夺:
1 | SHOW STATUS LIKE 'table%'; |
如果Table_locks_waited
值比较高,说明存在较严重的表级锁争用情况。
表级锁的锁模式
MySQL 表级锁有两种锁模式:表共享读锁(Table Read Lock
)和表独占锁(Table Write Lock
)
- 表共享读锁(
Table Read Lock
)
不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求。加锁如下:1
LOCK TABLE tb_name READ;
- 表独占锁(
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
,专门用以控制并发插入的行为。
- 当concurrent_insert设置为
0
时,不允许并发插入。 - 当concurrent_insert设置为
1
时,如果 MyISAM 表中没有空洞(即表中间没有被删除的行),允许一个进程读表的时间,另一个进行从表尾插入记录。 - 当concurrent_insert设置为
2
时,无论 MyISAM 表有没有空洞,都允许在表尾并发插入记录。
该并发插入特性用来解决应用中对同一表查询和插入的锁争用。
1 | -- 设置是否开启并发insert,0=不开启,1=没有空洞的情况下,允许insert,2=不管有没有空洞,都允许插入 |
MySQL系列(12): MyISAM 锁机制详解