mysql加锁/解锁函数
get_lock(str,timeout);
得到一个锁,锁名为str,持续时间为timeout。可以使用release_lock()或连接断开(正常非正常)解锁
若加锁成功:返回1
操作超时未:返回0
发生错误:返回去NULL
release_lock(str)
解开被get_lock加锁的锁
若锁被解开:返回1
若该线程尚未被创建锁:返回0(此时锁还没有解开)
若命名的锁不存在:返回NULL
若该锁从未被get_lock()的调用获取,或锁已经被提前解开:则该锁不存在
is_free_lock(str);
检查名为str的锁是否可以使用(没有被封锁)
若该锁可以使用(没有人在用这个锁):返回1
若锁正在被使用:返回0
出现错误:返回NULL
is_used_lock(str); //检查锁名为str的锁是否正在被使用(被封锁)
被封锁:返回使用该锁用户的客户端的连接标识符(connection ID)
否则:返回NULL
mysql分布式锁实现
加锁、释放锁必须在同一个session
示例
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import logging, time
import pymysql
class MysqLock:
def __init__(self, db):
self.db = db
def _execute(self, sql):
cursor = self.db.cursor()
try:
ret = None
cursor.execute(sql)
if cursor.rowcount != 1:
logging.error("Multiple rows returned in mysql lock function.")
ret = None
else:
ret = cursor.fetchone()
cursor.close()
return ret
except Exception as ex:
logging.error("Execute sql \"%s\" failed! Exception: %s", sql, str(ex))
cursor.close()
return None
def get_lock(self, lockstr, timeout):
"""
设置锁
"""
sql = "SELECT GET_LOCK('%s', %s)" % (lockstr, timeout)
ret = self._execute(sql)
if ret[0] == 0:
logging.debug("Another client has previously locked '%s'.", lockstr)
return False
elif ret[0] == 1:
logging.debug("The lock '%s' was obtained successfully.", lockstr)
return True
else:
logging.error("Error occurred!")
return None
def release_lock(self, lockstr):
"""
释放锁
"""
sql = "SELECT RELEASE_LOCK('%s')" % lockstr
ret = self._execute(sql)
if ret[0] == 0:
# 线程尚未被创建锁
logging.debug("The lock '%s' the lock is not released(the lock was not established by this thread).",
lockstr)
return False
elif ret[0] == 1:
# 锁被解开
logging.debug("The lock '%s' the lock was released.", lockstr)
return True
else:
# 锁不存在
logging.error("The lock '%s' did not exist.", lockstr)
return None
# Init logging
def init_logging():
sh = logging.StreamHandler()
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s -%(module)s:%(filename)s-L%(lineno)d-%(levelname)s: %(message)s')
sh.setFormatter(formatter)
logger.addHandler(sh)
logging.info("Current log level is : %s", logging.getLevelName(logger.getEffectiveLevel()))
def main():
init_logging()
db = pymysql.connect(host='localhost', user='root', passwd='123456')
lock_name = 'queue'
lock = MysqLock(db)
ret = lock.get_lock(lock_name, 10)
if not ret:
logging.error("Can't get lock! exit!")
quit()
time.sleep(10)
logging.info("You can do some synchronization work across processes!")
# TODO
# 可以处理一些事情
lock.release_lock(lock_name)
if __name__ == "__main__":
main()
参考:
https://www.jb51.net/article/51947.htm
https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html
网友评论