Mysql读锁定SELECT FOR UPDATE
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Mysql读锁定SELECT FOR UPDATE,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3264字,纯文字阅读大概需要5分钟。
内容图文
编辑
我使用node.js felixge-mysql并拥有一个mysql连接池.
原版的
我有一个mysql数据库,其中有2个表:
>“对话”,存储元数据:用户ID(2),主题,时间戳等.
>“messages”,存储具有带对话的FK的消息.id
现在我总是这样做:
>选择“对话”
>检查元数据是否允许请求的操作
>对“对话”执行更新(更改一些元数据,例如lastUpdatedTimestamp)
>可能将消息插入“消息”.
在消息旁边,用户也可以阻止对话(从他身边!)
会话UPDATE和可能的消息INSERT将在事务内发生.
需要注意的是:在我选择对话行并检查应用程序级别的元数据之后,可能是不允许请求的操作,导致更新并且可能的INSERT永远不会被执行!
Q1
现在如何从我选择它的那一刻开始锁定会话行?但是当元数据导致“用户错误”时(例如,当前userId不是“this”对话中的userId)仍然能够释放锁定.
Q2
现在我正在使用redis’lock’数据库,它通过使用Lua锁定给定的id并使用node.js事件来释放此锁.这些redis锁具有超时功能. (例如1000毫秒).有没有办法在mysql锁上设置超时?
解决方法:
你要完成什么并不完全清楚.但是,尽管我理解你的要求,但是没有任何原生的MySQL“锁定”机制可以满足您的需求. (您希望会话能够“锁定”一行以防止其被另一个会话“读取”(或修改).
要完成您尝试执行的操作,这听起来像应用程序问题,而不是数据库完整性问题.
我将用来解决这个问题的方法是向表中添加两列:
locked_by - uniquely identify the session holding the row lock
locked_at - the date/time the row lock was placed
对于尝试获取行锁定的会话,我将检查该行是否已被其他会话锁定,如果不是,则将该行标记为此会话锁定:
UPDATE mytable
SET locked_by = 'me'
, locked_at = NOW()
WHERE unique_row_identifer = someval
AND locked_by IS NULL;
如果更新返回“零行更新”,则表示您没有获得锁定.
如果返回值非零,则表示您获得了一个锁(至少在一行上).
要检查我的会话是否已在该行上持锁:
SELECT 1
FROM mytable t
WHERE t.unique_row_identifier = someval
AND locked_by = 'me';
一旦我知道我在行上有一个“锁定”,那么我可以用一个简单的SELECT来检索它
SELECT ... WHERE unique_row_identifier = someval`
要释放锁定,会话会将locked_by和locked_at列设置回NULL.
“只读”会话可以通过检查locked_by列中的值来避免读取锁定的行:
SELECT t.*
FROM mytable t
WHERE t.unique_row_identifier = someval
AND t.locked_by IS NULL
只有在未锁定的情况下才会返回该行.
请注意,我会在单个语句中执行锁定和检查,以避免出现同时出现的竞争条件.如果我运行SELECT来进行检查,然后进行UPDATE,那么另外一个会话可能会在这两个单独的语句之间滑动……很难真正导致这种情况发生,而不会增加显着的延迟.但是,如果我们要打扰锁定行,我们最好这样做.
请注意,当我们想要检查已经持有很长时间的锁时,存储在locked_at列中的值将起作用.也许会话占用了一些锁,并且该会话已经消失,并且这些锁永远不会被释放.可以安排单独的维护任务来查看表中是否存在非常旧的locked_at值.
或者,您可以使用locked_at为锁执行更复杂的查找,并考虑过期的旧锁.
WHERE ( locked_at IS NULL OR locked_at < (NOW() + INTERVAL 24 HOUR) )
===
注意:
我之前从未在生产系统中使用过这种方法.我的团队通常关心的问题是“胜利中的最后一个”场景,其中更新可能会覆盖最近另一个会话所做的更改.但是我们解决的问题似乎与你想要完成的问题有很大的不同.
要解决“胜利中的最后一个”问题,我们在表中添加一个“版本”列(简单整数).当我们检索一行时,我们检索版本列的当前值.当会话稍后想要更新该行时,它通过将先前检索的版本值与表中的当前值进行比较来验证没有对该行进行其他更新.如果版本号匹配,我们允许更新行,并将版本号增加1. (我们在一个UPDATE语句中完成所有操作,因此操作是原子操作,以避免两个同时会话都不进行更新的竞争条件.我们使用此模式是因为我们真的不想让行被锁定一个会话,永远保持锁定.我们只是阻止同时更新互相覆盖,这再次与你想要完成的声音不同.
内容总结
以上是互联网集市为您收集整理的Mysql读锁定SELECT FOR UPDATE全部内容,希望文章能够帮你解决Mysql读锁定SELECT FOR UPDATE所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。