I'm still confused about table row locking. I'm using MySQL/PHP and here is my scenario.
I have a set of tables that my application uses to keep track of requests and posts. A user creates a posting (table POSTING (P)) for an item (table ITEM (I)) and can send out requests to individual users (table REQUEST (R)) or can post it and receive post responses (table POSTING_RESPONSE (PR)) that will be accepted by user posting item.
Example: I am a user with a bike. I post it - and also send out requests to individual users. The users that receive the request from me can accept / reject / or do nothing. If they accept - it is reserved. Other users can find my posting and 'apply' for item. I have the ability to 'accept' or 'ignore' their request. If I accept, Item is reserved.
What I want to do if someone accepts request:
lock row in ITEM (I) table corresponding to item
lock row in POSTING (P) table (if row exists) corresponding to the item
lock row(s) in REQUEST (R) table for any requests sent for item
lock row(s) in POSTING_RESPONSE (PR) table (if rows exist) corresponding to item
update ITEM status to 'Reserved'
update POSTING status to 'Unavailable'
update all/any POSTING_RESPONSE to 'Rejected'
update all REQUEST to 'Rejected' besides the one that has accepted - update that one to 'Accepted'
Ignore the redundancy of status with this example please.
Now, I assumed that #1 - 4 could be done with a simiple "select ... for update" leaving AUTOCOMMIT as false. I could deterime with these select statements whether or not I should update - and if so, I can continue to the updates. Then after completion of updates #5-8, I would commit and rows would be unlocked.
I'm having problems getting this to work, and I don't know if it is because of something I'm doing or my thinking is incorrect.
One more thing... there are other processes that can update the status of the item to, say, EXPIRED or CANCELLED. I'm hoping that the only solution to my approach isn't to put every single possible condition in a WHERE clause within UPDATE statements... this would not be easily maintainable.
Mini-transaction: do it in one query.
UPDATE item
LEFT JOIN posting
ON posting.item_id = item.id -- or however
LEFT JOIN request
ON request.item_id = item.id -- or however
LEFT JOIN posting_reponse
ON posting_response.item_id = item.id
SET
item.status = 'Reserved',
posting.status = 'Unavailable',
posting_reponse.status = 'Rejected',
request.status = IF(request.id = some-current-id,'Accepted','Rejected')
WHERE item.id = some-id AND item.status='Available';
... and stop asking questions about locking for read, you really don't want that :P