欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > 数据库 >内容正文

数据库

Mysql 死锁过程及案例详解之用户自定义锁

发布时间:2024/9/27 数据库 37 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Mysql 死锁过程及案例详解之用户自定义锁 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

Mysql 用户自定义锁介绍

锁简介

当多个请求连接到数据库时,能保证同类查询执行时不相互冲突的机制即是锁。比如马路上的信号灯就是一个解决冲突的例子,在一定的时间内锁定了能通行的方向或者路线。MySQL里的锁实际上是一个处于处于授予或挂起状态锁请求。

锁的访问级别

锁的访问级别(Lock Access Levels)即定义锁以那种方式进入(使用)。主要有两种方式:共享的(shared)和排他的(exclusive)。

共享锁是比较宽松的锁,即允许多个连接访问。而排他锁则只能指定一个连接访问的锁。有时我们又称共享锁为读锁,排他锁为写锁。

锁的粒度

Mysql通过各种锁的粒度(类型)去控制数据的访问,这样可以尽可能的进行数据的并发访问。

用户自定义锁User-Level Locks

用户自定义锁是一种显式的锁,即用户通过数据库内置的函数生成锁。这些锁都是排他锁且可以指定的锁名最多64个字符。

函数名

功能

参数

额外说明

GET_LOCK

按照指定的名称、等待时间获得(生成)锁。

1 name 锁名

2 timeout 锁等待时间

1 timeout为正数时,如果在指定timeout连接上锁则返回1,否则返回0。

2 timeout为负数时会一直等待锁。

IS_FREE_LOCK

检查指定的锁是否可用

name 名字

可用返回1否则为0

IS_USED_LOCK

检查指定的锁是否已用

name 名字

如果锁可用时返回连接ID(connection id),不可用时返回NULL。

RELEASE_ALL_LOCKS

释放用户锁

返回锁的数量。

RELEASE_LOCK

释放指定的用户锁

name锁名

1 锁存在:释放成功返回1,否则为0(锁存在但不属于该连接时)。

2 锁不存在:返回null。

示意案例1

Step1:在第一个会话(session1)里执行:

SELECT GET_LOCK('lock_1',10); /*此时返回为: 1 -- 即可以生成锁lock_1。 */

Step2:此时在会话1里我们查看下锁的状态:

SELECT IS_USED_LOCK('lock_1') AS ISUsedLock, IS_FREE_LOCK('lock_1') AS ISFreeLock /*返回结果 ISUsedLock  ISFreeLock 10   0 */

Step3:而在另外个会话(session2)里执行:

SELECT GET_LOCK('lock_1',10);

即会话2里经过了10秒的尝试并不能获得锁lock_1。

Step4:如果在会话1里释放锁lock_1,那么会话2可以获得锁lock_1。

-- 会话1里释放锁lock_1。 SELECT RELEASE_LOCK('lock_1') /*返回结果 RELEASE_LOCK('lock_1') 1 */ -- 会话2里获得锁lock_1。 SELECT GET_LOCK('lock_1',10); /*返回结果 GET_LOCK('lock_1',10) 1 */

注:用户自定义锁是应用程序级别的锁,拿到锁的应用程序有排他性,并不针对特定的表和字段。

2 如果timeout设置为-1,那么在如上的实验中会话2会一直等待,直至会话1释放锁。

示意案例2

-- Step1:在第一个会话(session1)里执行: SELECT GET_LOCK('lock_1',-1);-- Step2:在第二个会话(session2)里执行: SELECT GET_LOCK('lock_2',-1);-- Step3:在第二个会话(session2)里执行: SELECT GET_LOCK('lock_1',-1);-- Step4:在第一个会话(session1)里执行: SELECT GET_LOCK('lock_2',-1);

解释:这里我们可以看到在会话1、会话2里分别生成锁lock_1、lock_2。接下来会话2去获取lock_1,这里是无限等待(timeout为-1)。然后在会话1又获取锁lock_2,此时就发生了死锁,因为会话2的连接当前还在尝试获取锁lock_1,无法释放lock_2,此时会话1访问锁lock_2就发生死锁。当一个连接处理多个锁时会出现死锁的情况。 

后续处理:分别在会话1、会话2里执行释放锁语句或者关闭连接自动释放锁。

这好比食堂里有两个人A、B都在用勺子1、2一个汤池里盛汤,但B在拿着勺2的情况下去等勺1,而A也想用B手里的勺2。这样显然会出现“冲突”,即如果双方都不谦让岂不是一直僵直在哪里了?!这就是死锁。

而对于其他分别在A、B后面排队的人,他们可能不知道A、B的状态,他们会一直等待A、B释放手中的勺子。

SELECT RELEASE_ALL_LOCKS()

自定义锁详情

通过数据字典查看用户自定义锁详情:

mysql> SELECT *-> FROM performance_schema.metadata_locks-> WHERE OBJECT_TYPE = 'USER LEVEL LOCK' \G *************************** 1. row ***************************OBJECT_TYPE: USER LEVEL LOCKOBJECT_SCHEMA: NULLOBJECT_NAME: my_lock_1COLUMN_NAME: NULL OBJECT_INSTANCE_BEGIN: 140483603134144LOCK_TYPE: EXCLUSIVELOCK_DURATION: EXPLICITLOCK_STATUS: GRANTEDSOURCE: item_func.cc:5452OWNER_THREAD_ID: 49OWNER_EVENT_ID: 139 *************************** 2. row ***************************OBJECT_TYPE: USER LEVEL LOCKOBJECT_SCHEMA: NULLOBJECT_NAME: my_lock_2COLUMN_NAME: NULL OBJECT_INSTANCE_BEGIN: 93976377610320LOCK_TYPE: EXCLUSIVELOCK_DURATION: EXPLICITLOCK_STATUS: GRANTEDSOURCE: item_func.cc:5452OWNER_THREAD_ID: 50OWNER_EVENT_ID: 62 *************************** 3. row ***************************OBJECT_TYPE: USER LEVEL LOCKOBJECT_SCHEMA: NULLOBJECT_NAME: my_lock_1COLUMN_NAME: NULL OBJECT_INSTANCE_BEGIN: 93976377962800LOCK_TYPE: EXCLUSIVELOCK_DURATION: EXPLICITLOCK_STATUS: PENDINGSOURCE: item_func.cc:5452OWNER_THREAD_ID: 50OWNER_EVENT_ID: 69 3 rows in set (0.00 sec)

总结

以上是生活随笔为你收集整理的Mysql 死锁过程及案例详解之用户自定义锁的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。