views:

37

answers:

1

I would like to know if locking my table is necessary in this situation (I'm using Coldfusion and MySQL):

I have a table called wishlists(memberId, gameId, rank, updateAt) where members store games in a personal list.

wishlists has a man-to-many with a members table, and many-to-many with a games table. Many members have many games stored in this list. These games are ranked using an int field. Ranks are particular to a member, so:

Member 1 can have itemId=1, rank=1; itemId=2, rank=2
Member 2 can have itemId=1, rank=1, itemId=2, rank=2
etc...

Each member can modify his or her list by deleting an item, or changing the rank of an item (sendGameToTopOfList(), deleteItemFromList(), for example). This means each time a change is made to a list, the list must be ranked again. I wrote a separate function called rankList() to handle re-ranking. It is fired after "deleteGameFromList()" or "sendGameToTopOfList(); it does the following:

1. Gets a memberWishlist query of all records @memberId ordered first by **rank ASC**, then **updateAt ASC** fields 
2. Loops through memberWishlist query and sets each row's **rank=memberWishlist.RecordCount**

updateAt field is necessary because if a game was moved to top of the list, we would have two items ranked number 1, and to differentiate them I use updatedAt.

Scenario One: A member has 100 games in their list:

  1. Member moves an item to top; rankList() is called after the operation is completed.
  2. While rankList() is still re-ranking the items, member deletes a game

In a normal page request this is fine as the page will not reload until rankList() is done. But if it were ajax, or if were using cfthread, the member can delete 10 games in 5 seconds by clicking through really quickly. Then again, the list will be re-ranked after delete anyway, so it may not matter; but it seems like it's something I should protect...

Scenario 2: Some of these wishlist items can turn into orders by using an additional field called "queuedForShipping." If queuedForShipping is 1, the rankList() function ignores them. What if an admin was creating a shipment when a member just deleted a item or moved one to the top?

Your thoughts are appreciated.

Additional information: New items are automatically ranked last at insert

+2  A: 

No. CFLock isn't going to have any effect on how MySQL handles things.

However, you might want a transaction. Wrapping your multiple operations in a transaction block will tell MySQL that you want to guarantee that all the operations complete before storing the changes permanently.

This assumes that your multiple queries are generated in CF, like this:

<cffunction sendToTopOfList()>
    <cfquery>
       send to top
    </cfquery>
    <cfquery>
        resort everything
    <cfquery>
</cffunction>

If you are using a stored procedure on the db server, then (1) I probably would not be too concerned about race conditions here, as you will likely apply row locks as the server makes changes, and (2) look into using transactions on the db server if you are still concerned.

If you still have questions, I'll try to answer them, although I'm not really a MySQL expert and haven't used it much in the last few years.

Ben Doom