“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 中 INDEX、PRIMARY、UNIQUE、FULLTEXT 之间的区别?

    创建MySQL表时PRIMARY UNIQUE INDEX和FULLTEXT有什么区别 我将如何使用它们 差异 KEY or INDEX指的是普通的非唯一索引 索引的非不同值是允许的 因此索引may索引的所有列中包含具有相同值的行 这些索引
  • 仅使用 varchar 作为外键的 MySQL 表

    我有一个包含单个唯一 VARCHAR 512 字段的表 我想让另一个表保存对第一个表的外键引用 两个表都使用 InnoDB 如果我向第二个表添加 VARCHAR 512 键并在其上添加外键约束 512 字节长的数据是否会保存两次 如果是这样
  • MySQL 中的创建/写入权限

    我的设备遇到一些权限问题SELECT INTO OUTFILE陈述 当我登录数据库并执行简单的导出命令时 例如 mysql gt select from XYZ into outfile home mropa Photos Desktop
  • 使用php插入sql数据库时出错

    我有一个带有 MySQL 插入查询的程序 sql INSERT INTO people person id name username password email salt VALUES person id name username p
  • PHP 和 MySQL 的重音字符错误

    我的问题是 直接通过 PHP 编写的内容是正确重音的 但是当重音单词来自 MySQL 时 字母会像这样 我尝试使用html charset as ISO 8859 1它修复了 MySQL 字母 但破坏了其他字母 解决这一切的一种方法是设置我
  • 如何使用php在mysql数据库中添加照片? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我对 PH
  • 在 .NET 并发线程之间传递数据的最佳方式是什么?

    我有两个线程 一个需要轮询一堆单独的静态资源以查找更新 另一种需要获取数据并将其存储在数据库中 线程1如何告诉线程2有东西要处理 如果数据块是独立的 则将数据块视为要由线程池处理的工作项 使用线程池和QueueUserWorkItem将数据
  • Volatile.Read 和 Volatile.Write 背后的逻辑是什么?

    来自 MSDN Volatile Read 读取字段的值 在需要它的系统上 插入一个 阻止处理器重新排序内存的内存屏障 操作如下 如果在该方法之后出现读或写 代码 处理器无法移动它before这个方法 and Volatile Write
  • ODBC 链接表中突然开始出现写入冲突消息

    我有一个 mySQL 数据库 用于跟踪我们的项目并驱动我们的网站显示其信息 为了方便更新数据库 我设置了一个使用 ODBC 连接 MySQL ODBC 5 1 来编辑数据的访问数据库 过去几个月一直运行良好 没有出现任何问题 然而 昨晚用户
  • 与通道相比,sync.WaitGroup 的优势是什么?

    我正在开发一个并发 Go 库 我偶然发现了 goroutine 之间两种不同的同步模式 其结果相似 等待组 https play golang org p ZYPLlcp16TZ package main import fmt sync t
  • Innodb页面大小设置

    在innodb中 页面大小默认为16kb 如何将页面大小设置为 8kb 是否有在源编译步骤中设置的选项 您不需要在源编译步骤中指定页面大小 MySQL 5 6 及更高版本支持不同的页面大小 无需重新编译 但是 您必须在初始化 InnoDB
  • 在 Django 查询中使用 .extra(select={...}) 引入的值上使用 .aggregate() ?

    我正在尝试计算玩家每周玩游戏的次数 如下所示 player game objects extra select week WEEK games game date aggregate count Count week 但姜戈抱怨说 Fiel
  • 使用 try {} catch {} 与 if {} else {} 相比有何优势

    我正在从 php 中的普通 mysql 切换到 PDO 并且我注意到测试错误的常见方法是使用 try catch 组合而不是 if else 组合 该方法的优点是什么 我可以使用一个 try catch 块而不是多个嵌套的 if else
  • 从java运行sqlplus脚本的简单方法

    我有包含 sqlplus 特定脚本的 sql 文件 它包括 或 作为语句终止符 执行存储过程的 EXEC 等 我需要从 java jdbc 执行此脚本 而不需要 sqlplus sql ant任务 maven sql插件无法处理不同的终止符
  • 使用 MySQL 的 CURDATE() 或 PHP 的 date() 更快?

    使用mysql查询是不是更快 SELECT CURDATE as today 或 PHP 语句 curdate date Y m d 同样的答案是否适用于使用date VS MySQL 的NOW and CURTIME 如果您只是执行查询以
  • 使用 Sequelize (NodeJS) 代替 * 指定特定字段

    好吧 我在 NodeJS 中有一个项目 我正在其中使用 Sequelize 来实现 MySQL ORM 这件事工作得非常好 但是我试图弄清楚是否有一种方法可以指定在查询的基础上返回哪些字段 或者是否有一种方法可以在某处执行 query 例如
  • 如何在php/mysql中使用事务

    我正在使用 php mysql 我知道 mysql 中的事务 但不能在我的脚本中使用 下面是我的脚本 如何在我的代码中使用 php 事务 即 BEGIN ROLLBACK COMMIT foreach json a shop as json
  • 使用 Laravel 和 Eloquent 从表中选择全部

    我正在使用 Laravel 4 设置我的第一个模型 以从名为的表中提取所有行posts 在标准 MySQL 中我会使用 SELECT FROM posts 如何在 Laravel 4 模型中实现这一目标 我的完整模型源代码如下
  • 在 Python 中,如果我有 unix 时间戳,如何将其插入 MySQL 日期时间字段?

    我正在使用 Python MySQLDB 我想将其插入 Mysql 中的 DATETIME 字段 我该如何使用cursor execute 来做到这一点 要将 UNIX 时间戳转换为 Python 日期时间对象 请使用datetime fr
  • Mysql 将 --secure-file-priv 选项设置为 NULL

    我在 Ubuntu 中运行 MySQL 我在运行特定的查询集时收到此错误 MySQL 服务器正在使用 secure file priv 选项运行 因此无法执行此语句 当我这样做的时候SELECT secure file priv 在我的 m

随机推荐

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

    下面是一个示例实现 它使用 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 我正在使用一