问题描述
场景:需要判断某条数据是否存在,如果不存在则插入该数据。在并发场景下,如果不做锁控制并且表上没有唯一键的话,就可能出现重复插入数据的情况。
例如,用户订购业务前判断下是否存在该业务,但是用户ID和业务ID并不是联合主键,并发场景下,两个会话同时查询某个用户是否有该业务订购关系时结果都是不存在,然后两个会话就会为该用户重复订购了该业务。
专家解答
通过行锁在查询用户会否有该订购关系前先锁定用户的某条数据
例如,锁定用户的信息表中的数据,这里肯定不能去锁定要插入的数据,因 为数据还不存在,也不能锁定公共数据,那样的话所有用户的并发都受影响 了。锁的方式最好是使用select for update,比update开销要小一些。
方案缺点:必须有适合锁定的数据,不够通用;必须在一个事务中,否则 commit后锁就不存在了。
咨询锁
咨询锁是用户自定义锁,COMMIT/ROLLBACK不会释放锁,需要用户显式的释放锁,会话中断会自动释放锁。
使用咨询锁可以不锁定任何用户数据解决这个问题,并且可以跨事务,推荐使用该方案。
- GET_LOCK(name_expr[, timeout_expr]) GET_LOCK()的返回值如下:
1: 成功获取到锁。
0: 未能获取到锁。 通过GET_LOCK()获取到的锁可通过以下两种方式释放:
显式释放:通过调用RELEASE_LOCK()释放
隐式释放:会话中断(不论正常或异常)时该会话占有的锁自动释放。 - RELEASE_LOCK(name_expr)
功能:通过锁名释放会话先前使用GET_LOCK()函数上的锁。 RELEASE_LOCK()的返回值如下:
1: 成功获取所指定的锁。
NULL: 当前会话并不占有所指定的锁。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




