Elemental race conditions question


#1

What’s the standard way to prevent race conditions in controllers?
Say user has many posts.

Post controller has action add_post that receives user id, post
controller find()s the user and while he is creating the post entry
an administrator deletes that user in a separate session. We cannot
assume the database checks foreign key integrity. How do you get that
right?

– fxn


#2

This isn’t a race condition, this is simply a data integrity issue. We
can’t assume the database checks foreign key integrity, but we can
program it to do so and that is a practice I recommend because it is
efficient and reliable.

The only other way to do this is to manage application locks yourself
with table columns, RoR will do automated optimistic locking if you
had a “lock_version” column to your tables. I doubt this will cover
this scenario though since its a delete rather than an update you are
concerned about but you’d have to do something similar in concept.


#3

On Mar 19, 2006, at 16:22, Jeremy H. wrote:

This isn’t a race condition, this is simply a data integrity issue.

I thought of it as a race condition between add_post and delete_user
because since add_post is not atomic it can find a user in one line,
assume it exists in the next one, and have delete_user break that in
between in a separate session.

If I could get a lock somehow, I could guarantee that when add_post
finishes the user is still there, which is all I am worried about, if
when the lock is released delete_user gets the lock and deletes the
user and his posts that’s fine (the rendered post listing in the
response of add_post might be out of sync, but that’s inherent to web
programming).

Just for the record this user/post scenario is indeed an imaginary
example that depicts the pattern.

We
can’t assume the database checks foreign key integrity, but we can
program it to do so and that is a practice I recommend because it is
efficient and reliable.

I am not familiar with database programming. What do you mean?
Programming it how? My application uses SQLite if that’s relevant.

– fxn


#4

On Mar 19, 2006, at 21:16, Jeremy H. wrote:

This isn’t a race condition because it doesn’t lead to a deadlock, its
just an example of a stale update that leaves the database in an
inconsistent state.

A deadlock is not a necessary condition of race condition as I
understand it. The definition of “race condition” I have in mind
coincides with the one in the Wikipedia[*]:

 A race hazard (or race condition) is a flaw in a system
 or process where the output exhibits unexpected critical
 dependence on the relative timing of events.

The example Received()/Timeout() is analogous to add_post/delete_user
in that regard.

We
specify declaratively in a database equipped to do so. I understand
sqlite doesn’t support FK constraints but it does support triggers, so
you could approach it that way. However, if your Rails app has a low
enough insertion volume to allow you to use sqlite you probably do not
need to worry about this question to begin with.

Yes, in this case that’s a simple application for internal use in the
client. I expect it will have three users that will go to it a couple
of times per month being optimistic :-), but I wanted to know the way
to address that nonetheless, to know the technique and add it to my
toolbox. I’ll follow your advice above next time, thank you!

– fxn

[*] http://en.wikipedia.org/wiki/Race_condition


#5

On 3/19/06, Xavier N. removed_email_address@domain.invalid wrote:

On Mar 19, 2006, at 16:22, Jeremy H. wrote:

This isn’t a race condition, this is simply a data integrity issue.

I thought of it as a race condition between add_post and delete_user
because since add_post is not atomic it can find a user in one line,
assume it exists in the next one, and have delete_user break that in
between in a separate session.

This isn’t a race condition because it doesn’t lead to a deadlock, its
just an example of a stale update that leaves the database in an
inconsistent state.

We
can’t assume the database checks foreign key integrity, but we can
program it to do so and that is a practice I recommend because it is
efficient and reliable.

I am not familiar with database programming. What do you mean?
Programming it how? My application uses SQLite if that’s relevant.

I just mean program it with foreign key constraints. The database is
in the best position to handle concerns like this and its very easy to
specify declaratively in a database equipped to do so. I understand
sqlite doesn’t support FK constraints but it does support triggers, so
you could approach it that way. However, if your Rails app has a low
enough insertion volume to allow you to use sqlite you probably do not
need to worry about this question to begin with.