Warm tip: This article is reproduced from serverfault.com, please click

其他-在MySQL / MAriaDB中强制释放用户级别的锁

(其他 - Force-release a user-level lock in MySQL/MAriaDB)

发布于 2020-12-02 16:37:35

我的会话管理(Zebra会话)使用用户级锁来避免同一会话中两个请求之间的争用情况。要开始会话,请使用GET_LOCK。关闭会话后,将使用RELEASE_LOCK。

MariaDB [planner_20201026]> select GET_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587aaaa', '5');
+-------------------------------------------------------------------+
| GET_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587aaaa', '5') |
+-------------------------------------------------------------------+
|                                                                 1 |
+-------------------------------------------------------------------+
1 row in set (0.000 sec)

MariaDB [planner_20201026]> select  RELEASE_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587aaa');
+-----------------------------------------------------------------+
| RELEASE_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587aaa') |
+-----------------------------------------------------------------+
|                                                            NULL |
+-----------------------------------------------------------------+
1 row in set (0.000 sec)

现在,由于某种原因,我处于一种情况,我不知道该锁在哪里没有正确释放。GET_LOCK由于超时而结束,RELEASE_LOCK告诉我它不能释放该锁,因为它(根据文档)是由另一个线程建立的:

MariaDB [xyz]> select GET_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587ac8b', '5');
+-------------------------------------------------------------------+
| GET_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587ac8b', '5') |
+-------------------------------------------------------------------+
|                                                                 0 |
+-------------------------------------------------------------------+
1 row in set (5.015 sec)

MariaDB [xyz]> select  RELEASE_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587ac8b');
+------------------------------------------------------------------+
| RELEASE_LOCK('session_ebe210e9b39f1ad3a409763be60efebff587ac8b') |
+------------------------------------------------------------------+
|                                                                0 |
+------------------------------------------------------------------+
1 row in set (0.000 sec)

现在,该会话已或多或少被阻止了/没用/被删除了,每个请求都要花费TIMEOUT秒。

我有什么机会可以清除该锁定,尤其是在超时之后?

Questioner
Ralf Jahr
Viewed
0
Bill Karwin 2020-12-03 01:06:20

你只能使用RELEASE_LOCK()释放在同一线程中获取的锁。一个线程没有特权强制另一个线程放弃其锁定。

如果你可以获取锁,但是任何其他线程都可以单方面迫使你释放它,那将是一个非常无用的锁系统!

解决此问题的一种方法是调用IS_USED_LOCK()告诉你哪个线程持有该锁。它返回持有者的整数线程ID;如果没有任何人持有该锁,则返回NULL。

然后,如果你具有SUPER特权,则你的线程可以杀死该其他线程,这将迫使它释放其锁(以及断开该客户端的连接)。但这是一件很不礼貌的事情。

我感觉这是一个XY问题你正在寻找一种强制释放其他线程持有的锁的解决方案,但这是一个糟糕的解决方案,因为它不能解决你的实际问题。

真正的问题是:

现在,由于某种原因,我处于一种情况,我不知道该锁在哪里没有正确释放。

你需要对此进行更认真的考虑,并设计一个不会丢失谁获得了锁的系统。

提示:GET_LOCK(name, 0)可能有帮助。这将立即返回(即超时为零秒)。如果可以获取该锁,则将其获取,并且GET_LOCK的返回值为1。如果该锁已经由另一个线程持有,则GET_LOCK仍会立即返回,但返回值为0,告诉你不能获得。