MyISAM存储引擎的表级锁

MyISAM存储引擎的表级锁

如果了解过文件锁的用法,那理解数据库锁就简单了。锁其实就协调多个进程或线程并发时,处理访问同一个资源的机制。在项目开发中,表锁是MySQL中作用范围较大的一种锁,它锁定的是用户操作的整张表,可以有效避免死锁的情况,且加锁速度快,消耗资源小。事情总有两面性,也就是因为表锁是锁了整张表,在并发的时候锁冲突更大,并发能力也就差

下面主要介绍MyISAM存储引擎的表级锁

一、表锁的分类

表锁根据操作的不同分为表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)

1、读锁

读锁表示用户读取数据(select)时添加的锁,此时不会阻塞其他用户对同一张表的读操作,但是会阻塞对同一张表的写请求

2、写锁

写锁表示用户对数据资源执行写(insert、update、delete)操作时添加的锁,此时除了当前添加写锁的用户外,其他用户都不能对表进行读、写操作,也就是说会阻塞其他用户对同一张表的读、写操作

MyISAM表的读操作与写操作,以及写操作之间是串行的

二、隐式的加锁

当用户操作select查询数据表时(MyISAM表),MySQL服务器会自动地为查询的表添加一个表读锁;当执行增删改(insert、delete、update)操作时,同样MySQL服务器也会自动地为操作的表添加一个表写锁;直到操作结束完毕,服务器为其自动解锁。

mysql> select * from order_step; 

查询一张7万记录的表,注意表的存储引擎为MyISAM; 查询时间差不多3-5秒。此时新开一个终端,执行更新操作

mysql> update order_step set statusinner=2001 where stepid=75584;
// 等待上一个终端执行结束

留意:

隐式加锁的时候,表的更新操作优先级高于表的查询操作。在添加写锁时,若表中没有任何锁则添加,否则排队等待。在添加读锁时,若表中没有写锁则添加,否则也将排队等待

三、显示加锁

用户一般不需要直接用LOCK TABLE命令给MyISAM表显示加锁。我们为了学习,显示加锁来在一定程度模拟事务操作

LOCK TABLES 数据表名 READ [LOCAL] WRITE,....

1、创建MyISAM表,准备实验环境.

CREATE TABLE `user`(
id INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50),
`money` DECIMAL(7,2)
)ENGINE=myisam CHARSET=utf8; 

INSERT INTO user(`username`,`money`) VALUES('乔峰',5);

2、显式加表锁

终端A:在自己操作表的时候,不希望其他用户去修改这这个表的数据

mysql> use demo;
Database changed
mysql> show tables;
+----------------+
| Tables_in_demo |
+----------------+
| tab_innodb     |
| user           |
+----------------+
2 rows in set (0.00 sec)

mysql> lock tables user read;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
+----+-----------+--------+
| id | username  | money  |
+----+-----------+--------+
|  1 | 乔峰      |   5.00 |
+----+-----------+--------+
1 rows in set (0.00 sec)

终端B

mysql> update user set money=money+5 where id=1;
// 等待终端A 释放锁

终端A 释放锁

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

3、支持并发时插入

在上面例子中,当终端A没有释放锁的时候,此时终端是不能update的,同时也不能insert。

mysql> insert into user(username,money) values('聂哥','100');
// 插入等待

考虑到并发的情况,我们在加锁的时候添加local选项。让其支持并发时插入

mysql> lock tables user read local;
Query OK, 0 rows affected (0.00 sec)

四、查询表级锁争用情况

mysql> show status like 'table%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Table_locks_immediate      | 86    |
| Table_locks_waited         | 0     |
| Table_open_cache_hits      | 2     |
| Table_open_cache_misses    | 0     |
| Table_open_cache_overflows | 0     |
+----------------------------+-------+
5 rows in set (0.01 sec)

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





posted @ 2021-09-05 18:36  成文的博客  阅读(110)  评论(0)    收藏  举报