For example, I have a row with a column
C1 value = 'clean', and two different clients run this query at the same time:
update T1 set C1 = 'dirty' where Id = 1
Without using transactions, is it guaranteed regardless of engine type that the value of
mysql_affected_rows() would be
1 for one client and
0 for the other?
Yes and No 🙂
In both cases, the access is serialised (assuming you’re using a transactional engine like InnoDB) since they hit the same row, so they won’t interfere with each other. In other words, the statements are atomic.
However, the affected row count actually depends on your configuration set when you open the connection. The page for mysql_affected_rows() has this to say (my bold):
For UPDATE statements, the affected-rows value by default is the number of rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to mysql_real_connect() when connecting to mysqld, the affected-rows value is the number of rows “found”; that is, matched by the WHERE clause.
And from the mysql_real_connect page:
CLIENT_FOUND_ROWS: Return the number of found (matched) rows, not the number of changed rows.
So, in terms of what happens with
CLIENT_FOUND_ROWS being configured, the affected rows for:
UPDATE T1 SET C1 = 'dirty' WHERE id = 1
have nothing to do with whether the data is changed, only what rows matched. This would be 1 for both queries.
On the other hand, if
CLIENT_FOUND_ROWS was not set, the second query would not actually be changing the row (since it’s already populated with ‘dirty’) and would have a row count of zero.
If you wanted the same behaviour regardless of that setting (only showing changes), you could use something like:
UPDATE T1 SET C1 = 'dirty' WHERE id = 1 AND C1 <> 'dirty'
MySQL is ACID-compliant if you use a transactional storage engine like InnoDB.