MYSQL中GET_LOCK()函数的使用
mysql版本: 8.0.17
在学习《高性能MYSQL 第三版》里7.4.3 事件这一章中,里面提到了函数GET_LOCK(),所以记录一下。
GET_LOCK(“lock1”,10):对名称为“lock1”的锁进行加锁。注意这里第二个参数“10”不是代表锁的有效时间10s,而是指这个连接会“监听” "lock1"这个锁10s,一旦这10s内其他连接释放了“lock1”锁,那么该连接会对"lock1"加锁成功。
加锁语句:1.SELECT GET_LOCK(“lock1”,2);
2.SELECT GET_LOCK(“lock1”,20);
此时执行语句:SELECT IS_FREE_LOCK(“lock1”);
返回0,表示"lock1"不是空闲锁,已经被占用
执行语句SELECT IS_USED_LOCK(“lock1”);可以查看目前占用该锁的连接id
3.执行SELECT RELEASE_LOCK(“lock1”);进行解锁操作。只有在加锁成功的那个连接里执行该语句才能够正常解锁。此时其他连接可正常对"lock1"进行加锁。
基本用法就是这些。有几个有意思的点,记录一下。
释放锁除了执行SELECT RELEASE_LOCK()语句外,断开连接也会释放锁。
1.在连接1里执行,SELECT GET_LOCK(“lock1”,20);此时连接1加锁成功
2.分别在连接2,连接3里执行SELECT GET_LOCK(“lock1”,20);语句,此时2个连接会一直处于"等待"状态,等待20s。
3.在连接1里执行SELECT RELEASE_LOCK(“lock1”)或者直接断开连接,那么此时连接1,连接2其中先进入“等待”状态的会先获得锁。猜测:内部可能会有一个等待队列。
第二个有趣的地方:如果连接1 SELECT GET_LOCK(“lock1”,20)加锁成功,那么在连接1里继续执行SELECT GET_LOCK(“lock1”,20);会再加一道锁,此时如果想释放锁,那么需要执行SELECT RELEASE_LOCK(“lock1”) 2次才能释放成功
附:《高性能MYSQL 第三版》中7.4.3事件中使用GET_LOCK()的原文:
如果一个定时事件需要执行很长时间,那么有可能会出现这样的情况,即前面一个事件还未执行完成,下一个时间点的事件又开始了。MySQL本身不会防止这种并发,所以需要用户自己编写这种情况下的防并发代码。你可以使用函数GET_LOCK()来确保当前总是只有一个事件再执行:
CREATE ECENT optimize_somedb ON SCHEDULE EVERY 1 WEEK DO BEGIN DECLARE CONTINUE HANLDER FOR SQLEXCEPTION BEGIN END; IF GET_LOCK('somedb',0) THEN DO CALL optimize_tables('somedb'); END IF; DO RELEASE_LOCK('somedb'); END