mysql的 myisam引擎锁问题
作者:网络转载 发布时间:[ 2016/10/14 10:26:26 ] 推荐标签:MySQL 数据库
一,概述
相对其他数据库而言,mysql的锁机制比较简单,其显著的特点是不同的存储引擎支持不同的锁机制。比如:myisam和memory存储引擎采用的是表级锁,bdb采用的是页面锁,但也支持表级锁,innodb存储引擎即支持行级锁也支持表级锁,但默认情况下是行级锁。
三种锁的特性大致归纳如下:
(1)表级锁:开销小,加锁快;不会出现死锁;锁粒度大,发生冲突的概率高,并发度低。
(2)行级锁:开销大,加锁慢;会出现锁死;锁粒度小,发生锁冲突的概率低,并发度也高。
(3)页面锁: 开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。
所以,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用。而行级锁则更适合于有大量按照索引条件并发更新少量不同数据,同时又有并发查询的应用。
二,myisam表锁
1,通过查看状态变量来分析系统上表锁定争夺
mysql> show status like 'table_lock%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Table_locks_immediate | 101 |
| Table_locks_waited | 0 |
+-----------------------+-------+
2 rows in set (0.00 sec)
以上两个数据,如果table_locks_waited的值更高,则说明存在较严重的表级锁争用情况。
2,表级锁的锁模式
mysql的表级锁有两种模式:表共享读锁(table read lock)和表独占写锁(table write lock)。锁模式的兼容性如下:
mysql表锁兼容性 none 读锁 写锁 读锁 是 是 否 写锁 是 否 否
可见,对myisam表的读操作不会阻塞其他用户对同一表的读操作,但会阻塞对同一表的写操作.
对myisam表的写操作则会阻塞其他用户对同一表的读和写操作。
myisam表的读操作与写操作之间,以及写操作之间是串行的。
下面我们来看一个例子:
首先,我们创建表并插入几条数据,看一下表的结构:
mysql> create table t18(id int auto_increment primary key,name varchar(63),age int(3));
Query OK, 0 rows affected (0.33 sec)
mysql> insert into t18(name,age)values('fzy1',1),('fzy2',2),('fzy3',3);
Query OK, 3 rows affected (0.07 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from t18;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | fzy1 | 1 |
| 2 | fzy2 | 2 |
| 3 | fzy3 | 3 |
+----+------+------+
3 rows in set (0.00 sec)
写阻塞读例子 session_1 session_2 获得表t18的write锁
mysql> lock table t18 write;
Query OK, 0 rows affected (0.00 sec)
当前session对锁定的表的查询,更新,插入操作都可以执行
mysql> insert into t18(name,age)values('fzy4',4);
Query OK, 1 row affected (0.04 sec)
mysql> update t18 set age=5 where id=2;
Query OK, 1 row affected (0.11 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from t18;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | fzy1 | 1 |
| 2 | fzy2 | 5 |
| 3 | fzy3 | 3 |
| 4 | fzy4 | 4 |
+----+------+------+
4 rows in set (0.00 sec)
其他session对锁定的表操作被阻塞
mysql> select * from t18;
等待
释放锁
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
等待 session2获得锁,返回查询结果
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | fzy1 | 1 |
| 2 | fzy2 | 5 |
| 3 | fzy3 | 3 |
| 4 | fzy4 | 4 |
+----+------+------+
4 rows in set (1 min 21.56 sec)
读阻塞写例子 session_1 session_2 获得t18的read锁定
mysql> lock table t18 read;
Query OK, 0 rows affected (0.00 sec)
当前session可以查询该表记录
mysql> select * from t18;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | fzy1 | 1 |
| 2 | fzy2 | 5 |
| 3 | fzy3 | 3 |
| 4 | fzy4 | 4 |
+----+------+------+
4 rows in set (0.00 sec)
session_2也可以获得该表记录
mysql> select * from t18;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | fzy1 | 1 |
| 2 | fzy2 | 5 |
| 3 | fzy3 | 3 |
| 4 | fzy4 | 4 |
+----+------+------+
4 rows in set (0.00 sec)
当前session不能查询未锁定的表,但可以看锁定的表(这个会话中锁定的表)
mysql> select * from t17;
ERROR 1100 (HY000): Table 't17' was not locked with LOCK TABLES
其他session可以查询和更新未锁定的表
mysql> select * from t17;
+----+------+------+--------+
| id | name | age | intro |
+----+------+------+--------+
| 1 | fzy1 | 1 | intro1 |
| 2 | fzy2 | 2 | intro2 |
| 3 | fzy3 | 3 | intro3 |
| 4 | hsq | 4 | intro4 |
+----+------+------+--------+
4 rows in set (0.00 sec)
当前session中插入或更新数据都会报错
mysql> insert into t18(name,age)values('fzy5',5);
ERROR 1100 (HY000): Table 't18' was not locked with LOCK TABLES
其他session更新锁定的表会等待获得锁
mysql> insert into t18(name,age)values('fzy6',6);
等待
释放锁
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
等待 获得锁执行
Query OK, 1 row affected (2 min 33.25 sec)
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11