[LRUG] Fwd: Transactions
roland.swingler at gmail.com
Thu Dec 13 04:22:05 PST 2012
And... forward to the list
---------- Forwarded message ----------
From: Roland Swingler <roland.swingler at gmail.com>
Date: Thu, Dec 13, 2012 at 12:20 PM
Subject: Re: [LRUG] Transactions
To: Andrew Stewart <boss at airbladesoftware.com>
Have a look at the optimistic locking in rails - see this class:
basically, you include a lock_version column on the table, which is
just an incrementing number. When the second transaction tries to
commit, instead of working it will raise an ActiveRecord::StaleObject
error, which you can then deal with (probably by reloading the record
and trying again).
There is also pessimistic locking, which locks the rows at the
database level iirc:
but I've not used that, and depending on how busy your system gets may
lead to contention for the locks.
Hope that helps.
On Thu, Dec 13, 2012 at 12:14 PM, Andrew Stewart
<boss at airbladesoftware.com> wrote:
> Afternoon all,
> I have successfully confused myself with (mysql) database transactions – hopefully someone can enlighten me.
> Here's the scenario: a book can be checked out from a library. When that happens, the book's state is updated from available to out and a loan record is created recording who checked out the book. The code looks like:
> class Book < ActiveRecord::Base
> has_many :loans
> state_machine initial: 'available' do
> state 'available' do
> transition on: :transition_check_out, to: 'out'
> state 'out' do
> # ...
> def check_out(person)
> ActiveRecord::Base.transaction do
> if transition_check_out # (1)
> loans.create checked_out_by_id: person.id
> # (2)
> sleep 5 # (3)
> (1) Handled by the state_machine gem. It's equivalent to (AFAIK):
> if state == 'available' && update_attributes state: 'out'
> (2) I assume the book is already checked out (to this person) thanks to a double-click on the GUI.
> (3) The sleep is to make the problem easier to reproduce.
> The idea is that if there's a double-click on the check-out form in the GUI, the book won't end up with two loan records representing the same loan in real life. However occasionally and reproducibly I can get two loan records like this:
> - Process 1 executes and starts sleeping at (3).
> - Process 2 starts a new transaction and cannot see the pending results of process 1's transaction. It (process 2) thinks the book is available and so updates it to out and creates a loan. Process 2 starts sleeping.
> - Process 1 commits its transaction.
> - Process 2 commits its transaction. There are now two "duplicate" loans.
> I've reached the lamentable stage where the more I think about this, the less I understand :p
> Any help would be much appreciated.
> BTW this follows up:
> Thanks in advance,
> Andy Stewart
> Chat mailing list
> Chat at lists.lrug.org
More information about the Chat