登录
注册
开源
企业版
高校版
搜索
帮助中心
使用条款
关于我们
开源
企业版
高校版
私有云
模力方舟
AI 队友
登录
注册
代码拉取完成,页面将自动刷新
捐赠
捐赠前请先登录
取消
前往登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
Watch
不关注
关注所有动态
仅关注版本发行动态
关注但不提醒动态
31
Star
32
Fork
225
openGauss
/
Plugin
代码
Issues
50
Pull Requests
1
Wiki
统计
流水线
服务
JavaDoc
PHPDoc
质量分析
Jenkins for Gitee
腾讯云托管
腾讯云 Serverless
悬镜安全
阿里云 SAE
Codeblitz
SBOM
我知道了,不再自动展开
51
兼容mysql用户锁,实现支持字符串的advisory用户锁
已关闭
用户已删除:master
openGauss:master
xiuqiangwang
创建于 2022-04-17 21:25
克隆/下载
HTTPS
SSH
复制
下载 Email Patch
下载 Diff 文件
### **特性背景:** 本需求目的,为实现类MySQL用户锁功能。 本功能的主要设计目的,是在数据库中,提供更灵活的编程模式,允许用户通过sql加自定义的锁,可以让多个程序之间完成加锁相关的交互过程。 用户锁的主要使用场景,是作为应用开发中的程序锁,或者用于记录锁的模拟,因为锁是加在服务端的,客户端从任何位置访问都可以得到一致性的锁视图。 比如一个场景:有个存储在共享文件系统的文件,允许读写,会有多个程序去读写这个文件,这种情况下,如果出现交叉访问,可能导致文件内容错误,那么这个时候,就可以考虑使用文件路径或者名称,作为字符串申请到用户锁之后,才允许对这个文件读写。因为持有锁只有一个会话,读写这个文件时候不会受到其他人干扰,保证了一致性和安全性。 以上是例子,实际使用中,为了避免相互干扰,一般建议锁字符串的形态为app_name.str或者db_name.str这种形态,避免无必要的冲突。 由于对database关键字处理不同,MySQL,database1对应到OG的schema概念而非database概念,因此用户锁功能加在database级别而非全局,不同database可以对同一字符串加锁。 本文档目标为解释清楚MySQL用户锁功能的使用方式,限制,以及主要的参与人行为。 事务锁: 数据库进行数据操作时候,对数据加的锁 程序锁: 数据库内部为了保护数据结构等目的,对数据结构加的锁 用户锁: 会话中针对某个字符串加的排他锁,持有后其他会话无法对这个字符串加锁。 参考文档:https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html ### **特性描述** 1. 实现函数GET_LOCK 对指定字符串加锁 2. 实现函数IS_FREE_LOCK 判断锁是否空闲 3. 实现函数IS_USED_LOCK 寻找使用锁的会话 4. 实现函数RELEASE_ALL_LOCKS 释放所有的锁 5. 实现函数RELEASE_LOCK 释放指定的锁 6. 实现函数GET_ALL_LOCKS 查询当前所有用户锁的名字和持有人信息 **(1)加锁GET_LOCK** 1. 功能描述 对数据库中指定字符串加用户锁。 函数设计为GET_LOCK(str,timeout),以及GET_LOCK(str),timeout可以为字符串也可以为数字。 2. 接口规则 由于设计限制,暂不支持连接池场景。 当一个锁成功拿到后,除了当前会话,其他会话是无法再拿到这个字符串对应的锁的,必须等待当前会话释放锁,或者持有锁的会话断开或退出之后自动释放掉所有持有的锁。 成功拿到锁之后,如果会话中对事务进行了commit或者rollback操作,都不会影响到锁的持有。 一个会话可以持有多个用户锁,或者对一个锁持有多次(也可以解释为对同一个字符串加锁多次),当持有多次的情况下,释放时候需要释放对应的次数。 申请到的用户锁以及申请行为可以在dbe_perf.pg_locks视图看到,对应行的lockname列会显示申请到的锁的名称字符串。 允许单个用户持有多个锁的情况下,就会产生死锁。对于无限制时间的等锁行为,会被数据库自身的lwlock死锁发现机制发现并识别到,如果发现死锁,则选择一个会话的求锁请求中断掉(由LWLOCK死锁发现机制决策),对于被中断的求锁行为,返回用户锁求锁错误。 参考实现中,用户锁最大允许字符长度为64字符,因此目前实现中也以此作为参考。 由于没有对锁申请数量进行限制,对于类似insert into xxx SELECT GET_LOCK(t1.col_name) FROM t1;的用法是允许的。 这条sql预期的目标,是对表t1中,查询出来的每个col_name行对应的字符串进行加锁。然后把执行结果插入到xxx表中(姑且不讨论这种操作的实际意义),这样的情况下,如果dml执行到中间失败了,那么会出现一部分锁加上,一部分锁没有加上的情况,对于没有确定顺序的select,重复执行可能导致这一系列的加锁行为是无序的,存在加锁乱序的问题(间接可能导致死锁)。 3. 接口描述 执行之后,尝试获取针对指定str的锁,并指定超时时间timeout,单位秒,如果不指定超时时间,或者指定为0,负数,认为可以无限等待。执行后,如果成功拿到锁,返回1,如果超时,返回0,如果有其他错误,返回null(如会话等锁期间被kill)。 4. 加锁用例 SELECT GET_LOCK('lock1'); SELECT GET_LOCK('lock2',10); SELECT GET_LOCK('lock3',-1); 此时,查询pg_locks表,可以看到持有lock1,lock2,lock3三个锁。 SELECT RELEASE_LOCK('lock1'); SELECT RELEASE_LOCK('lock2'); SELECT RELEASE_LOCK('lock3'); 对于不同会话的锁: SELECT GET_LOCK('lock1'); 如果是连接到同一个database的不同会话,后求锁者会陷入等待。 如果是连接到不同database的会话,则都可以申请成功锁。 SELECT GET_LOCK('lock2',10); 对于不同会话的锁:如果尝试申请一个已经持有的锁,超过指定时间(秒)之后,如果依然没有拿到锁,则返回求锁失败。 SELECT GET_LOCK('lock3',-1); 对于不同会话的锁:后求锁的会话会陷入无限等待。 **死锁问题:** 预备环境:会话1 持有锁s1,会话2 持有锁s2 执行sql,在会话1执行求s2的get_lock(无限制超时时间),在会话2执行求s1的get_lock(无限制超时时间),此时预期现象是会话1或者会话2的其中一个会话求锁行为会返回失败。 **(2)指定的锁是否空闲IS_FREE_LOCK** IS_FREE_LOCK(str) 检查字符串是否空闲,如果没有被加锁返回1,否则返回0,如果检查期间出现其他错误,返回NULL。 **(3)指定锁的持有者IS_USED_LOCK** IS_USED_LOCK(str) 检查字符串的锁被谁持有,返回对应的用户的会话id,如果指定锁无人持有,返回NULL。 **(4)释放所有的锁RELEASE_ALL_LOCKS** 释放当前会话持有的所有的锁,返回释放的次数(对于单个字符串持有多个的情况,按对应数字计算而非只计算一次)。 RELEASE_ALL_LOCKS() **(5)释放锁RELEASE_LOCK** RELEASE_LOCK(str) 释放指定的锁,如果释放成功,返回1,如果当前会话并未持有指定锁,返回0,如果当前锁并不存在(锁必须有人持有才会出现),返回NULL。 如果锁的最后一个持有人释放了,那么锁就会从锁列表中删除掉。 **(6)查询当前所有用户锁的名字和持有人信息GET_ALL_LOCKS** GET_ALL_LOCKS() 查询当前库中的所有用户锁,以记录的形式返回所有用户锁的名字和持有人信息。
怎样手动合并此 Pull Request
git checkout master
git pull https://gitee.com/opengauss/Plugin.git master
git push origin master
评论
12
提交
5
文件
4
检查
代码问题
0
批量操作
展开设置
折叠设置
审查
Code Owner
审查人员
吴岳川
wuyuechuan
chenxiaobin
chenxiaobin19
pengjiong
totaj
熊小军
xiong_xjun
wumingyuan
wumingyuan
陈栋
chendong76
zhaosiqi
dreamalloc
jeremytim
jeremytim
胡正超
gentle_hu
zhaojun
kelayzhao
huyinghao
yinghaohu
zhangxubo
zhang_xubo
Mijamind
quemingjian
laishenghao
dodders
zhoujingbnu
zhoujingbnu
刘伟
llzx373
douxin
ywzq1161327784
wangfeihuo
wangfeihuo
jinbo
l1azzzy
liuchangfeng
superblaker
libiao
libiao2024
jemappellehc
jemappellehc
siven_dev
siven_dev
CodeRejector
zankyfun4
未设置
最少人数
0
测试
吴岳川
wuyuechuan
chenxiaobin
chenxiaobin19
pengjiong
totaj
熊小军
xiong_xjun
wumingyuan
wumingyuan
陈栋
chendong76
zhaosiqi
dreamalloc
jeremytim
jeremytim
胡正超
gentle_hu
zhaojun
kelayzhao
huyinghao
yinghaohu
zhangxubo
zhang_xubo
Mijamind
quemingjian
laishenghao
dodders
zhoujingbnu
zhoujingbnu
刘伟
llzx373
douxin
ywzq1161327784
wangfeihuo
wangfeihuo
jinbo
l1azzzy
liuchangfeng
superblaker
libiao
libiao2024
jemappellehc
jemappellehc
siven_dev
siven_dev
CodeRejector
zankyfun4
未设置
最少人数
0
优先级
不指定
严重
主要
次要
不重要
标签
opengauss-cla/yes
ci-pipeline-failed
关联 Issue
I52UVT
兼容mysql用户锁,实现支持字符串的advisory用户锁
Pull Request 合并后将关闭上述关联 Issue
里程碑
未关联里程碑
参与者
(4)
1
https://gitee.com/opengauss/Plugin.git
git@gitee.com:opengauss/Plugin.git
opengauss
Plugin
Plugin
点此查找更多帮助
搜索帮助
Git 命令在线学习
如何在 Gitee 导入 GitHub 仓库
Git 仓库基础操作
企业版和社区版功能对比
SSH 公钥设置
如何处理代码冲突
仓库体积过大,如何减小?
如何找回被删除的仓库数据
Gitee 产品配额说明
GitHub仓库快速导入Gitee及同步更新
什么是 Release(发行版)
将 PHP 项目自动发布到 packagist.org
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册