If I have a simple statement as such for an InnoDB Table
UPDATE <table> SET locked=1, col2=<Val2> WHERE locked=0
Is there any need to really do SELECT FOR UPDATE?
Since InnoDB supports row level locking is there any chance of a collision even thousands of clients are executing the same script simultaneously?
Update:
Something like this would prevent locks
$dbh = new PDO(DSN, DB_USER, DB_PASS);
$dbh->beginTransaction();
$selQuery = $dbh->prepare("SELECT <col> FROM <table> WHERE status=0 LIMIT 1 FOR UPDATE");
$selQuery->bindColumn(<col1>, $col1);
$selQuery->execute();
$selQuery->fetch(PDO::FETCH_BOUND);
$dbh->query("UPDATE <table> SET status=1 WHERE status=0 LIMIT 1");
$dbh->commit();
Yes, collisions can always occur. So using the design pattern:
SELECT FOR UPDATE
for all the resources in a given transaction first, can prevent or shorten deadlock situations.
Suppose the following scenario:
Now process A updates, table 1, with process B updating table 2 at the same time, causing a deadlock (assumption is that the same "records/pages" are hit by this update).
If however the SELECT FOR UPDATE
would be used in the start of the transaction, the transaction would block at the start since table 2 (or 1 whomever is faster) can not be locked (yet). The key part here is "At the start of the transaction", if you do it later, then just running the UPDATE
is just as efficient.
Key is always to keep your transactions atomic and fast: Group the SQL logic so it can execute with the least amount of other code in between, keep lock times as short as possible.