views:

30

answers:

2

I'm writing a strategy-kind of multi user game for the web. It has a playfield (X by Y squares) that I plan on serialize and store in a BLOB in a MySQL (innodb) database, one row for each ongoing game.

I now try to figure out a good way of keeping the database updated with any changes to the playfield, and at the same time finding a convenient solution to how to handle things that happen to the playfield in the time frame between loading the page and actually making a move.
I don't use AJAX.

There will be at most 20 players in each game, each player making between 1 and 10 moves in 24 hours, so it is a "slow" game.

My plan (so far) is to also store a kind of checksum for the playfield next to the blob and compare the databases state with the state loaded before trying to make changes to the playfield.

What I worry about is how to prevent race conditions.
Is it enough to:

  1. Begin transaction.
  2. load playfield from table
  3. if checksum differs - rollback and update the users view
  4. if checksum unchanged - update table and commit changes

Is the BEGIN TRANSACTION enough to block the race, or do I need to do something more in step 2 to show my intent to update the table?

Thankful for all advice.

A: 

No. You will need to issue a LOCK TABLES command for the tables you need to protect against conflicting updates. This would look something like...

LOCK TABLE my_table WRITE;

More details may be found here... http://dev.mysql.com/doc/refman/5.1/en/lock-tables.html

Don't forget to UNLOCK them afterwards!

Brian Hooper
LOCK TABLE will work, but is more heavy-handed than is necessary. It's better to lock only the row(s) you need.
nathan
+2  A: 

If you use SELECT ... FOR UPDATE when you load the playfield from the database, it will block other selects until you commit or rollback the transaction.

nathan
Great. Does my "algorithm" look sane as well? I mean, am I guaranteed that two (or any number of) threads that simultaneously perform the 2 steps above (with `FOR UPDATE`) will be serialized so only 1 process at a time can access the relevant row?
MattBianco
Yes, once one thread issues the SELECT FOR UPDATE on the row, all other threads will stall on their SELECT FOR UPDATE until that transaction is complete. Then the next thread that gets through will read the updated row.
nathan