龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 数据库类 > MySQL 技术 >

Mysql数据库锁定机制详细介绍(3)

时间:2014-12-02 02:53来源:网络整理 作者:网络 点击:
分享到:
如果满足了上面两个条件之后,该请求会被立即通过,并将相关的信息存入Currentread-lockqueue中,而如果上面两个条件中任何一个没有满足,都会被迫进入等

如果满足了上面两个条件之后,该请求会被立即通过,并将相关的信息存入Currentread-lockqueue中,而如果上面两个条件中任何一个没有满足,都会被迫进入等待队列Pendingread-lockqueue中等待资源的释放。

写锁定

当客户端请求写锁定的时候,MySQL首先检查在Currentwrite-lockqueue是否已经有锁定相同资源的信息存在。

如果Currentwrite-lockqueue没有,则再检查Pendingwrite-lockqueue,如果在Pendingwrite-lockqueue中找到了,自己也需要进入等待队列并暂停自身线程等待锁定资源。反之,如果Pendingwrite-lockqueue为空,则再检测Currentread-lockqueue,如果有锁定存在,则同样需要进入Pendingwrite-lockqueue等待。当然,也可能遇到以下这两种特殊情况:

1. 请求锁定的类型为WRITE_DELAYED;
2. 请求锁定的类型为WRITE_CONCURRENT_INSERT或者是TL_WRITE_ALLOW_WRITE,同时Currentreadlock是READ_NO_INSERT的锁定类型。

当遇到这两种特殊情况的时候,写锁定会立即获得而进入Current write-lock queue 中

如果刚开始第一次检测就Currentwrite-lockqueue中已经存在了锁定相同资源的写锁定存在,那么就只能进入等待队列等待相应资源锁定的释放了。

读请求和写等待队列中的写锁请求的优先级规则主要为以下规则决定:

1. 除了READ_HIGH_PRIORITY的读锁定之外,Pendingwrite-lockqueue中的WRITE写锁定能够阻塞所有其他的读锁定;
2. READ_HIGH_PRIORITY读锁定的请求能够阻塞所有Pendingwrite-lockqueue中的写锁定;
3. 除了WRITE写锁定之外,Pendingwrite-lockqueue中的其他任何写锁定都比读锁定的优先级低。

写锁定出现在Currentwrite-lockqueue之后,会阻塞除了以下情况下的所有其他锁定的请求:

1. 在某些存储引擎的允许下,可以允许一个WRITE_CONCURRENT_INSERT写锁定请求
2. 写锁定为WRITE_ALLOW_WRITE的时候,允许除了WRITE_ONLY之外的所有读和写锁定请求
3. 写锁定为WRITE_ALLOW_READ的时候,允许除了READ_NO_INSERT之外的所有读锁定请求
4. 写锁定为WRITE_DELAYED的时候,允许除了READ_NO_INSERT之外的所有读锁定请求
5. 写锁定为WRITE_CONCURRENT_INSERT的时候,允许除了READ_NO_INSERT之外的所有读锁定请求

随着MySQL存储引擎的不断发展,目前MySQL自身提供的锁定机制已经没有办法满足需求了,很多存储引擎都在MySQL所提供的锁定机制之上做了存储引擎自己的扩展和改造。

MyISAM存储引擎基本上可以说是对MySQL所提供的锁定机制所实现的表级锁定依赖最大的一种存储引擎了,虽然MyISAM存储引擎自己并没有在自身增加其他的锁定机制,但是为了更好的支持相关特性,MySQL在原有锁定机制的基础上为了支持其ConcurrentInsert的特性而进行了相应的实现改造。

而其他几种支持事务的存储存储引擎,如Innodb,NDBCluster以及BerkeleyDB存储引擎则是让MySQL将锁定的处理直接交给存储引擎自己来处理,在MySQL中仅持有WRITE_ALLOW_WRITE类型的锁定。

由于MyISAM存储引擎使用的锁定机制完全是由MySQL提供的表级锁定实现,所以下面我们将以MyISAM存储引擎作为示例存储引擎,来实例演示表级锁定的一些基本特性。由于,为了让示例更加直观,我将使用显示给表加锁来演示:RITE_ALLOW_READ 类型的写锁定。

Session a

Session b

 

行锁定基本演示

 

1

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

 

mysql> update test_innodb_lock set b = 'b1' where a = 1;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

更新,但是不提交

 

2

 

mysql> update test_innodb_lock set b = 'b1' where a = 1;

被阻塞,等待

3

mysql> commit; Query OK, 0 rows affected (0.05 sec) 提交

 

4

 

mysql> update test_innodb_lock set b = 'b1' where a = 1;

Query OK, 0 rows affected (36.14 sec)

Rows matched: 1 Changed: 0 Warnings: 0

解除阻塞,更新正常进行

 

无索引升级为表锁演示

 

5

mysql> update test_innodb_lock set b = '2' where b = 2000;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql> update test_innodb_lock set b = '3' where b = 3000;

被阻塞,等待

6

   

7

mysql> commit; Query OK, 0 rows affected (0.10 sec)

 

8

 

mysql> update test_innodb_lock set b = '3' where b = 3000;

Query OK, 1 row affected (1 min 3.41 sec)

Rows matched: 1 Changed: 1 Warnings: 0

阻塞解除,完成更新

 

间隙锁带来的插入问题演示

 

9

mysql> select * from test_innodb_lock;

+------+------+ | a | b |+------+------+

| 1 | b2 |

| 3 | 3 |

| 4 | 4000 |

| 5 | 5000 |

| 6 | 6000 |

| 7 | 7000 |

| 8 | 8000 |

| 9 | 9000 |

| 1 | b1 |

+------+------+

9 rows in set (0.00 sec)

mysql> update test_innodb_lock set b = a * 100 where a < 4 and a > 1;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1 Changed: 1 Warnings: 0

 

10

 

mysql> insert into test_innodb_lock values(2,'200');

被阻塞,等待

11

mysql> commit;

Query OK, 0 rows affected (0.02 sec)

 

12

 

mysql> insert into test_innodb_lock values(2,'200');

Query OK, 1 row affected (38.68 sec)

阻塞解除,完成插入

 

使用共同索引不同数据的阻塞示例

 

13

mysql> update test_innodb_lock set b = 'bbbbb' where a = 1 and b = 'b2';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

 

14

 

mysql> update test_innodb_lock set b = 'bbbbb' where a = 1 and b = 'b1'; 被阻塞

15

mysql> commit;

Query OK, 0 rows affected (0.02 sec)

 

16

 

mysql> update test_innodb_lock set b = 'bbbbb' where a = 1 and b = 'b1'; Query OK, 1 row affected (42.89 sec)

Rows matched: 1 Changed: 1 Warnings: 0

session 提交事务,阻塞去除,更新完成

 

死锁示例

 

17

mysql> update t1 set id = 110 where id = 11;

Query OK, 0 rows affected (0.00 sec)

Rows matched: 0 Changed: 0 Warnings: 0

 

18

 

mysql> update t2 set id = 210 where id = 21;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

19

mysql>update t2 set id=2100 where id=21;

等待sessionb释放资源,被阻塞

 

20

 

mysql>update t1 set id=1100 where id=11;

Query OK,0 rows affected (0.39sec)

Rows matched: 0 Changed: 0 Warnings:0

精彩图集

赞助商链接