Rails 在事务中,为什么锁定整个数据库而不是单个记录?

Rails In Transaction, why is entire database locked instead of single record?

我正在经历这个。在事务中,数据库本身是阻塞的,而不是单条记录。

这是我的代码片段。

代码 1)

lesson = Lesson.last
ActiveRecord::Base.transaction do
lesson.start_time = Time.now
  lesson.save
  sleep(10.seconds)
  raise "let's roll back lesson!!"
end

代码 2)

lesson = Lesson.first
lesson.start_time = Time.now
lesson.save

我在控制台 1 中执行代码 1,在另一个终端打开的控制台 2 中执行代码 2。很明显两个控制台在本地共享数据库。

代码 2 抛出类似

的错误
ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: UPDATE "lessons" SET "start_time" = ?, "updated_at" = ? WHERE "lessons"."id" = ?

我假设代码 1 将阻止 lesson(Lesson.last) 由于引发的异常而被修改。它工作正常,但与我的预期相反的是代码 2 没有更新课程(Lesson.first)。

如果是这种性质(阻塞整个数据库,而不是单个记录),那么复杂的业务逻辑最终将因事务停止而受到影响。

有点好奇!让代码 2 正常工作的好策略是什么!

详细说明我们在评论中写的内容:

ActiveRecord Transactions are per-database connection, not per-model.

https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

在开发环境下,Sqlite3不支持concurrent modification到数据库