MySQL IS_FREE_LOCK() 函数使用指南

MySQL IS_FREE_LOCK() 是一个轻量级的只读探针函数,用于判断指定名称的咨询锁当前是否处于完全空闲、无人持有的可用状态。

与直接调用可能导致线程等待或挂起的加锁动作不同,IS_FREE_LOCK() 执行速度极快且完全无阻塞,常用于分布式节点启动自检、集群主备竞争前置预判以及定时监控脚本中。

MySQL IS_FREE_LOCK() 语法

这里是 MySQL IS_FREE_LOCK() 函数的标准语法:

IS_FREE_LOCK(str)

参数

str
必需的。拟检测的目标命名锁名称字符串。

返回值

MySQL IS_FREE_LOCK() 返回一个整数或 NULL:

  • 1:锁是空闲的,当前没有任何客户端连接持有该锁。
  • 0:锁正在被使用,已被某个连接持有。
  • NULL:执行过程中出现错误(例如传入非法的入参)。

MySQL IS_FREE_LOCK() 示例

以下示例演示 IS_FREE_LOCK() 的检测逻辑与典型应用模式。

基础检测:空闲与占用状态比对

在全新会话中检查一个尚未被申请的锁:

SELECT IS_FREE_LOCK('warehouse_inventory_sync') AS is_free;

输出:

+---------+
| is_free |
+---------+
|       1 |
+---------+

此时如果另一个会话通过 GET_LOCK('warehouse_inventory_sync', 10) 成功持有了该锁,再次查询:

SELECT IS_FREE_LOCK('warehouse_inventory_sync') AS is_free;

输出:

+---------+
| is_free |
+---------+
|       0 |
+---------+

业务预检场景:快速跳过已被占用的任务

在多 worker 轮询任务队列的分布式批处理系统中,worker 可以先通过 IS_FREE_LOCK() 做快速旁路过滤,避免每个 worker 都阻塞在锁争夺上:

SELECT 
    task_id, 
    task_name,
    CASE 
        WHEN IS_FREE_LOCK(CONCAT('task_mutex_', task_id)) = 1 THEN 'READY'
        ELSE 'RUNNING'
    END AS execution_status
FROM scheduled_tasks
LIMIT 5;

输出:

+---------+--------------------+------------------+
| task_id | task_name          | execution_status |
+---------+--------------------+------------------+
|     101 | 邮件批量发送       | READY            |
|     102 | 日志归档压缩       | RUNNING          |
|     103 | 统计报表预生成     | READY            |
|     104 | 支付对账流水       | RUNNING          |
|     105 | 索引碎片重组       | READY            |
+---------+--------------------+------------------+

通过这一查询,控制台可以直观展示各任务的实时并行状态。

结论

  • IS_FREE_LOCK() 仅仅提供瞬间的只读快照状态。
  • 并发竞态警示(TOCTOU):检查结果返回 1 并不保证下一毫秒你调用 GET_LOCK() 时一定能成功拿到锁,因为其他并发连接可能在两者之间抢先加锁。
  • 严肃的临界区保护务必以 GET_LOCK(name, timeout) 的原子性返回值作为准入判定依据,IS_FREE_LOCK() 主要服务于状态呈现与旁路监控。