82
51

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RailsのTransactions、Lock 初心者→中級者へのSTEP17/25

Last updated at Posted at 2018-12-17

#RailsのTransactions、Lock
##はじめに
前回のTransactionsの応用で今回はデータのロックについてです

##データのロック?
DBにおけるロックとはトランザクションが対象データにロックをかけて占有することです。
これはデータの競合を防ぐためです。
二つのトランザクションが同時に起きると、データに一貫性が持てないことがあります。
例としてはこちらのページがわかりやすかったので、参考にしてください。

##Railsでロックするには
実装方法は2つ、lockwith_lockがあります。

    User.transaction do
      user = User.lock.find(1)
      user.update!(name: 'taro')
    end

最初にlockメソッドです。チェインして使います。これでトランザクション中はロックされます。処理中は**読み取りは可能です。**更新処理等は待たされます。

次に、with_lockメソッドです。こちらはトランザクションとロックが同時にできます。

  user = User.first
  user.with_lock do
    user.update!(name: 'taro')
  end

##注意点
今回のロックの仕方は悲観的ロックと呼ばれ、ロックしないとデータは競合するだろうという推測の元するロックのやり方で、厳格なロックとなります。利用できるDBMSはPostgresかMySQLとなりますのでご注意を。

##試してみる。
参考記事でもコンソール2つ使ってデータがロックされているか試してたので確認してみます。

irb(main):028:0> user = User.first
irb(main):032:0>    user.with_lock do
irb(main):033:1*       sleep 30      
irb(main):034:1>    end              
   (0.1ms)  begin transaction
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?   [["id", 1], ["LIMIT", 1]]

~~~~~~~~~~30秒後~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   (0.2ms)  commit transaction
=> 30

この間に他のコンソールでuserを更新してみます。

irb(main):026:0> user.update(name: 'locking')
   (0.1ms)  begin transaction
  SQL (0.8ms)  UPDATE "users" SET "updated_at" = ?, "name" = ? WHERE "users"."id" = ?  [["updated_at", "2018-12-17 13:16:12.614654"], ["name", "locking"], ["id", 1]]
   (5045.1ms)  commit transaction
   (2.0ms)  rollback transaction
ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: commit transaction

ちゃんとロックされてます。待ち時間が長いので戻されてます。

##まとめ
データベースも学び直したくなってきた今日この頃。

##参考にしたの

Railsのデータロック
https://qiita.com/merrill/items/d9d41d64df292bd6432a

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

トランザクションの一貫性を保証するロック
http://www.atmarkit.co.jp/ait/articles/0212/21/news003.html

ActiveRecord::Locking::Pessimistic
https://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html

Railsで悲観的ロック(PostgreSQLの行レベルロック)
https://qiita.com/upinetree/items/b3329501561268f7678a

82
51
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
82
51

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?