当前位置: 首页 > 知识库问答 >
问题:

为什么我在锁定的 ActiveRecord 查询生成的 SQL 中看不到“FOR UPDATE”?

淳于兴朝
2023-03-14

我正在阅读“The Rails 5 Way”,在第191页我看到以下内容:

悲观锁定发生在数据库级别。由活动记录生成的SELECT语句将添加一个FOR UPDATE(或类似的)子句...

Rails文档似乎包含相同的信息:

锁定::Pessimistic支持使用SELECT… FORUPDATE和其他锁类型的行级锁定。

将 ActiveRecord::Base#find 链接到 ActiveRecord::QueryMethods#lock 以获取所选行的独占锁:

< code > account . lock . find(1) # SELECT * FROM accounts,其中id=1用于更新

作为一个实验,我想在我的本地机器上重现这个<code>FOR UPDATE</code>语句。我知道用悲观锁定启动事务的方法是调用<code>。lockclass方法(本书给出了t=Timesheet.lock.first的示例)。因此,我在一个玩具Rails应用程序(v5.1.6)的REPL中运行了以下代码,其中包含一个Order类:

irb(main):015:0> Order.transaction do       
irb(main):016:1* o1 = Order.lock.first
irb(main):017:1> o1.update_attributes(name: 'Foo Bar')
irb(main):018:1> end

这产生了以下产出:

(0.3ms)  begin transaction
Order Load (0.2ms)  SELECT  "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT ?   [["LIMIT", 1]]
SQL (1.1ms)  UPDATE "orders" SET "name" = ?, "updated_at" = ? WHERE "orders"."id" = ?  [["name", "Foo Bar"], ["updated_at", "2018-11-04 03:01:35.593868"], ["id", 1]]
(0.4ms)  commit transaction
=> true

我在SELECTUPDATE语句中都没有看到FORUPDATE。在尝试指定悲观锁定时,我是否做错了什么?或者我对应该输出的SQL有不正确的期望?

共有1个答案

刘高驰
2023-03-14

我发现我的玩具应用程序使用的是默认的Rails sqlite数据库。我创建了一个新的玩具应用程序(rails new newbie --database=postgresql),创建了一个包含多个实例的新用户模型,并运行User.lock.first,我看到了以下内容:

irb(main):004:0> User.lock.first
  User Load (1.7ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 FOR UPDATE  [["LIMIT", 1]]
=> #<User id: 1, name: nil, phone: nil, created_at: "2018-11-05 01:28:23", updated_at: "2018-11-05 01:28:23">

如您所见,FORUPDATE出现在SQL查询中。从这个Stack Overflow答案中,我看到默认情况下SQLite不支持悲观锁定:

选择。。。对于更新...不受支持。考虑到该行锁定中的SQLite机制是多余的,这是可以理解的,因为在更新任何位时整个数据库都会被锁定。

 类似资料:
  • 问题内容: 有没有办法像在开发中一样查看生产环境中从Rails生成的所有查询? 问题答案: 是的你可以。如果进入config / environments / production.rb文件,则有类似以下内容的部分: 取消注释config.log_level行,您将在生产中获得与在开发中相同的日志。

  • 我已经使用开发人员沙盒帐户构建了一个集成。我最近将我的应用程序升级为live,并将我的生产环境配置为使用新的集成id和secret以及live Docusign url。 但是,当我尝试在应用程序的帐户中创建oauth连接时,我的服务器会获取一个代码,将客户端重定向到Docusign以进行身份验证,但Docusign登录屏幕显示错误“没有向Docusign注册的重定向URI”。事实并非如此-我的开

  • 但是生成的SQL查询是 正如您所看到的,括号改变了,我相信两个查询中的条件并不相同。是虫子吗?使用hibernate和spring以及postgresql数据库。

  • 问题内容: 有没有办法观察将由生成的SQL语句? 例如,我有这个:是否 可以查看其基础的原始SQL? 问题答案: 光滑2.X: 您可以按照Slick文档中所示打印查询语句: 对于其他类型的报表看,和。 光滑的3.X: 文件。

  • 以前它工作正常,但现在一切都很慢,而且我没有看到TextField,在层次结构中选择游戏对象时,在编辑器窗口中显示它需要将近5秒的时间。 在此之前,一切都很快,并在编辑器窗口中显示整个层次结构。 现在它是空的: 我从这个问题中得到了答案: 可通过计算机搜索的

  • 问题内容: 我想查看发送到PostgreSQL服务器的SQL命令,因为我需要检查它们是否正确。我特别对表创建命令感兴趣。 例如,ActiveRecord(Ruby)将其SQL语句打印到标准输出。Node.js / ActionHero.js和Sequelize.js也可能吗? 问题答案: 您可以在初始化sequelize时传递日志记录选项,该选项可以是函数或console.log。 如果只想查看表