“FOR UPDATE”v/s“LOCK IN SHARE MODE”:允许并发线程读取锁定行的更新“状态”值

2024-04-14

我有以下场景:

  • 用户 X 从位置 lc1 登录到应用程序:调用它Ulc1
  • 用户 X(已被黑客攻击,或者他的某个朋友知道他的登录凭据,或者他只是从他计算机上的不同浏览器登录,等等。你明白了)从位置 lc2 同时登录:调用它Ulc2

我正在使用一个主 servlet:
- 从数据库池获取连接
- 将自动提交设置为 false
- 执行穿过应用程序层的命令:如果全部成功,则在“finally”语句中将 autocommit 设置为 true,然后关闭连接。否则如果发生异常,则回滚()。

在我的数据库(mysql/innoDb)中,我有一个“历史”表,其中包含行列:
id(主键)|用户名|日期 |主题 |锁定

“locked”列的默认值为“false”,它用作标记特定行是否被锁定的标志。
每行都特定于一个用户(正如您从用户名列中看到的那样)

回到场景:
-->Ulc1 发送命令至update他的历史记录来自日期“D”和主题“T”的数据库。

-->Ulc2 发送same命令到update数据库的历史记录same日期“D”和same主题“T”位于完全相同的时间。

我想实现一个 mysql/innoDB 锁定系统,该系统将使到达的任何线程都可以执行以下检查:

该行的列“锁定”是否正确?

  • 如果为 true,则向用户返回一条消息“他已经从另一个位置更新相同的数据”
  • 如果不是 true(即未锁定):将其标记为锁定并更新,然后在完成后将锁定重置为 false。

这两种 mysql 锁定技术中的哪一种实际上将允许第二个到达的线程读取锁定列的“更新”值来决定要采取的 wt 操作?

我应该使用“用于更新” or “锁定共享模式”?

这个场景解释了我想要实现的目标:
- Ulc1 线程先到达:列“locked”为 false,将其设置为 true 并继续更新过程
- Ulc2 线程在 Ulc1 的事务仍在处理中时到达,即使该行通过 innoDb 功能锁定,它也不必等待,但实际上读取了锁定列的“新”值,即“true”,等等事实上不必等到 Ulc1 事务提交来读取“锁定”列的值(无论如何,到那时该列的值已经被重置为 false)。

我对这两种类型的锁定机制不是很有经验,到目前为止我所理解的是 LOCK IN SHARE MODE 允许其他事务读取锁定的行,而 FOR UPDATE 甚至不允许读取。但是这个读取是否得到了更新后的值?或者第二个到达的线程必须等待第一个线程提交然后读取该值?

任何关于在这种情况下使用哪种锁定机制的建议都是值得赞赏的。
另外,如果有更好的方法来“检查”该行是否已被锁定(除了使用真/假列标志之外),请告诉我。
谢谢

SOLUTION
(基于Jdbc伪代码示例@达哈泽的回答)

表:[ id(主键)|用户名|日期 |主题 |已锁定]

connection.setautocommit(false);
//transaction-1
PreparedStatement ps1 = "Select locked from tableName for update where id="key" and   locked=false);
ps1.executeQuery();

//transaction 2
PreparedStatement ps2 = "Update tableName set locked=true where id="key";
ps2.executeUpdate();
connection.setautocommit(true);// here we allow other transactions threads to see the new value

connection.setautocommit(false);
//transaction 3
PreparedStatement ps3 = "Update tableName set aField="Sthg" where id="key" And date="D" and topic="T";
ps3.executeUpdate();

// reset locked to false
 PreparedStatement ps4 = "Update tableName set locked=false where id="key";
ps4.executeUpdate();

//commit
connection.setautocommit(true);

锁定共享模式将允许第二个线程读取该值,但实际值将是查询之前(已提交读)或事务(可重复读)启动之前的值(因为 MySQL 使用多版本控制;以及什么)必须由第二个事务看到是由隔离级别定义的)。因此,如果第一个事务在读取时未提交,则将读取旧值。

在您的场景中,最好有 1 个事务通过选择更新来锁定记录,而不是在记录上工作并在提交/回滚时使用第三个事务来解锁记录。

具有 select for update 的第二个线程事务将等待第一个事务完成,然后将读取实际值并决定不继续其他事务,而是通知用户该记录已锁定。

为了避免死锁,请确保您正在执行以下操作select for update使用唯一索引。

示例代码:

connection.setautocommit(false);
//transaction-1
PreparedStatement ps1 = "Select locked from tableName for update where id="key" and   locked=false);
ps1.executeQuery();

//transaction 2
PreparedStatement ps2 = "Update tableName set locked=true where id="key";
ps2.executeUpdate();
connection.setautocommit(true); // here we allow other transactions / threads to see the new value

connection.setautocommit(false);
//transaction 3
PreparedStatement ps3 = "Update tableName set aField="Sthg" where id="key" And date="D" and topic="T";
ps3.executeUpdate();

// probably more queries

// reset locked to false
 PreparedStatement ps4 = "Update tableName set locked=false where id="key";
ps4.executeUpdate();

//commit
connection.setautocommit(true);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“FOR UPDATE”v/s“LOCK IN SHARE MODE”:允许并发线程读取锁定行的更新“状态”值 的相关文章

  • 单行的总和值?

    我有一个 MySQL 查询 它返回由一系列 1 和 0 组成的单行 它用于进度条指示器 我现在在代码中对它进行求和 但我尝试对查询中的值求和 并意识到我无法使用 SUM 因为它们有很多列 但只有一行 有没有办法可以在查询中自动求和 就像这样
  • 如何以最少的查询次数获取帖子列表和关联标签

    我的表格结构如下 标签 更多的是一个类别 id 标签名称 描述 slug POSTS ID 标题 网址 邮戳 id idPost idTag USERS ID 用户名 userSlug VOTES id idPost idUser 每个帖子
  • 有哪些学习线程编程的好资源? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 随着多核CPU在桌面上的兴起 多线程技能将成为程序员的宝贵资产 您能为想要学习线程编程的程序员推荐一些好的资源 书籍 教程 网站等 吗 看
  • Glassfish 4 - JDBC 领域

    Glassfish 4 中的密码加密算法和摘要算法有什么区别 因为Password加密算法不能为空 所以我使用了MD5 Encoding使用了Hex 摘要算法为空 因此默认为 SHA 256 但是 如果我使用 JAAS 制作一个简单的登录应
  • 社交应用程序的数据库设计和优化注意事项

    通常的情况 我有一个简单的应用程序 允许人们上传照片并关注其他人 因此 每个用户都会有类似 墙 或 活动源 的东西 他或她可以在其中看到他 她的朋友 他或她关注的人 上传的最新照片 大多数功能都很容易实现 然而 当涉及到这个历史活动源时 由
  • 如何在 phpmyadmin 中创建 MySQL 触发器

    我想在 MySQL 中创建一个触发器 我运行以下命令 mysql gt delimiter mysql gt CREATE TRIGGER before insert money BEFORE INSERT ON money gt FOR
  • 显示表 FULLTEXT 索引列

    我希望运行一个查询 该查询将返回表中全文索引的列列表 该表采用 MyISAM 格式 我将使用 php 来构建查询 理想情况下 我会运行查询 它会返回信息 以便我可以构造一个以逗号分隔的列字符串 例如 名 姓 电子邮箱 这在 MySQL 中可
  • 如何在 Laravel 查询中使用多个 OR,AND 条件

    我需要 Laravel 查询帮助 我的自定义查询 返回正确结果 Select FROM events WHERE status 0 AND type public or type private 如何写这个查询Laravel Event w
  • 并发集合和独特元素

    我有一个并发BlockingCollection具有重复的元素 如何修改它以添加或获取不同的元素 默认后备存储BlockingCollection is a ConcurrentQueue 正如其他人指出的那样 使用它来添加不同的项目相当困
  • 为什么这会返回资源 id #2? [复制]

    这个问题在这里已经有答案了 可能的重复 我如何从 PHP 中的 MySql 响应中 回显 资源 id 6 https stackoverflow com questions 4290108 how do i echo a resource
  • 无法通过套接字“/var/lib/mysql/mysql.sock”连接到本地 MySQL 服务器 (2)

    当我尝试连接 mysql 时出现以下错误 Can t connect to local MySQL server through socket var lib mysql mysql sock 2 这个错误有解决办法吗 其背后的原因可能是什
  • Apache、PHP 和 MySQL 可移植吗?

    我可以在外部硬盘上运行 Apache PHP 和 MySQL 吗 我需要这个 因为我在不同的地方工作 计算机 有时我没有安装和配置所有使用的应用程序 当然可以 XAMPP http www apachefriends org en xamp
  • MySQL MIN/MAX 所有行

    我有桌子Races与行ID Name and TotalCP 我选择分钟 TotalCP FROM Races 但是我想选择具有最小值的整行 我如何在单个查询中做到这一点 从聚合值获取整行的一般形式是 SELECT FROM Races W
  • 将第三个表链接到多对多关联中的桥接表

    设计这个数据库的正确方法是什么 这是我设置表格的方式 我在名为 教师 的表和名为 仪器 的表之间存在多对多关系 然后我有一个连接两者的桥接表 我想将另一个表与 BRIDGE 表关联起来 意思是乐器 老师的组合 该表有 3 行 指定老师可以教
  • 在文件复制/上传未完成时读取文件内容

    例如 每 5 秒 服务器检查文件是否已添加到特定目录 如果是 它会读取并处理它们 相关文件可能非常大 例如 100 Mo 因此将它们复制 上传到上述目录可能会很长 如果服务器尝试访问尚未完成复制 上传的文件怎么办 JAVA是如何管理这些并发
  • 在服务器上找不到本地主机或 phpMyAdmin:如何修复?

    我按照安装说明进行操作PHP MySQL and PHPMyAdmin 但是当我尝试访问时http localhost phpmyadmin 我收到此错误 未找到 在此找不到请求的 URL phpmyadmin 服务器 然后我尝试访问loc
  • 如何使用 SparkR 1.6.0 写入 JDBC 源?

    使用 SparkR 1 6 0 我可以使用以下代码从 JDBC 源读取数据 jdbc url lt jdbc mysql localhost 3306 dashboard user
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • SQL不允许表中有重复记录

    如何使其不添加重复项 我想让它通过 ID 之外的所有其他列进行检查 我希望这个无效 ID col1 col2 col3 1 first middle last ID col1 col2 col3 2 first middle last 我希
  • 如何修改现有表以添加时区

    我有一个包含 500 多个表的大型应用程序 我必须将应用程序转换为时区感知 当前应用程序使用new java util Date GETDATE 与服务器的时区 即没有任何时区支持 我已将这项任务分为几个步骤 以便于开发 我确定的第一个步骤

随机推荐

  • 将异步结果分配给数据绑定属性

    下面是一个示例实现 它使用 Metro API 和数据绑定 使用 MVVM 来填充下拉列表中的文件夹列表 View 模型的构造函数使用 SetFolders 方法 私有异步 该方法调用可等待方法 fileService GetFolders
  • Gulp-autoprefixer 抛出 ReferenceError: Promise 未定义

    我尝试让 gulp 编译我的 sass 然后使用 autoprefixitgulp autoprefixer但我收到错误 var gulp require gulp sass require gulp sass autoprefixer r
  • 清理 .NET 中动态 SQL 中的表/列名称? (防止SQL注入攻击)

    我正在生成一些动态 SQL 并希望确保我的代码是安全的SQL注入 http en wikipedia org wiki SQL injection 为了便于论证 这里是一个关于如何生成它的最小示例 var sql string Format
  • 乘以数据表中的列

    我有一个 C 数据表 其中包含 价格 列和 分配 列 我需要将价格列乘以分配列 并将结果放入价格列中 有没有一种方法可以在不循环桌子的情况下进行 我尝试过这样的事情 DataTable dt getData dt Columns Price
  • 函数输出函数文本而不是预期输出

    我已经用几种不同的方式提出了类似的问题 但这是最简单的版本 我试图在函数发生时通过键名值列表进行递增 但是 当调用该函数时 我得到的只是函数本身的文本 这是一个片段 var knlist kn10 2L1qvq6Tg6rMhEwNshr6d
  • 两个相互依赖的字段的淘汰验证

    考虑下面的代码 var MyObjectModel function myObject var self this self myNumber1 ko observable myObject number1 trimmed self myN
  • 从Azure功能(powershell)访问IP受限的URI

    我想知道给定的 Powershell 函数 例如 url http AnIPrestrictedURL xml xml new object System Net WebClient DownloadString url url 是一个 I
  • 如何在 JavaScript 中使用单选按钮将用户发送到新网站?

    我希望程序做的是制作一个表单并有 2 个单选按钮和 1 个文本 然后我希望它将文本和单选值折叠在一起并将我带到该页面 如果我输入类似 facebook 的文本 并且单选按钮值为 com 我希望它采用 facebook com 并将我发送到该
  • 升级到 razor 2 / mvc 4 后,为什么我的 razor 视图抱怨“}预期”?

    我有一个现有的 razor 1 mvc 3 视图 有一些嵌套if 非常简单 但是升级到 razor 2 mvc 4 后 它在运行时和编译时抱怨 BuildViews about expected 它曾经工作得很好 我已经检查了所有元素是否格
  • Flask 运行与 Python

    我很难使用 python 方法运行我的烧瓶应用程序 我使用没有问题 export FLASK APP microblog py flask run 但尝试使用 python microblog py 会导致以下错误 ImportError
  • 在代码块中链接头文件

    所以我在 OpenCV 中编写了代码 其中包含使用 Code Blocks 的 2 个头文件 当我编译文件时 除了两个 未定义的引用 错误之外没有任何错误 这是因为我使用了在头文件中声明的函数 我假设代码块自动链接头文件 我已经使用 inc
  • PIC18F 中的随机种子

    我将在 PIC18F2550 微控制器上运行修改后的 DES 代码 C 语言 为此 我使用 mplabx IDE v 2 和 Mplab xc8 v 1 30 要修改代码 我需要一个随机数 以便每次运行都会产生不同的数字 我想使用 rand
  • Geany编译

    不知道该把这个放在哪里 但我在 2 个系统 笔记本电脑和台式机 上运行 Geany 在我的笔记本电脑上它运行得很好 但在我的台式机上运行代码时出现此错误 whatevername 不被识别为内部或外部命令 可操作程序或批处理文件 我不知道w
  • 使用 Pandas 的欧几里得距离矩阵

    我有一个 csv 文件 其中包含以下格式的城市 纬度和经度数据 CITY LATITUDE LONGITUDE A 40 745392 73 978364 B 42 562786 114 460503 C 37 227928 77 4019
  • C++ pow 函数得到一个奇怪的结果[重复]

    这个问题在这里已经有答案了 使用某些版本的 minGW 以下代码将打印 99 int high high pow 10 2 std cout lt
  • String.IndexOf 方法的表达式树

    我应该如何构建表达式树string IndexOf substring StringComparison OrdinalIgnoreCase 我可以在没有第二个参数的情况下让它工作 StringComparison OrdinalIgnor
  • 是否有一种与系统无关的方法来确定表示当前目录级别和父目录级别的字符串?

    C 代码可以运行的不同环境对于文件和目录路径必须是什么样子有不同的约定 规则 一个常见的示例是分隔目录级别的字符 在 Windows 上 它是 在Linux上 它是 还有其他 也是未来的 系统可能遵循不同的规则 因此 为了创建健壮的代码 建
  • PostgreSQL:将结果与标题复制/粘贴到 Excel 中,无需代码

    我使用 MS SQL Server 2008 R2 MS SQL 我可以右键单击查询结果 将其与标题一起复制 粘贴到 Excel 中 以便于探索 现在使用 PG Admin PostgreSQL 我必须执行导出 文件 gt 导出 gt CS
  • 如何使用 .NET XML API 删除 xmlns 属性

    XmlElement Attributes Remove 方法对于任意属性都可以正常工作 导致已删除的属性从 XmlDocument OuterXml 属性中删除 然而 Xmlns 属性是不同的 这是一个例子 XmlDocument doc
  • “FOR UPDATE”v/s“LOCK IN SHARE MODE”:允许并发线程读取锁定行的更新“状态”值

    我有以下场景 用户 X 从位置 lc1 登录到应用程序 调用它Ulc1 用户 X 已被黑客攻击 或者他的某个朋友知道他的登录凭据 或者他只是从他计算机上的不同浏览器登录 等等 你明白了 从位置 lc2 同时登录 调用它Ulc2 我正在使用一