For instance, I've got a row having a column C1 value = 'clean', and 2 different computer systems run this question:

UPDATE T1
  SET C1 = 'dirty'
WHERE id = 1

simultaneously.

Without needing transactions, could it be guaranteed that the need for mysql_affected_rows() could be 1 for just one client and 0 for that other?

It depends :-)

In the two cases, the access is serialised (presuming you are utilizing a transactional engine like InnoDB) given that they hit exactly the same row, so that they will not hinder one another. Quite simply, the claims are atomic.

However, the affected row count really is dependent in your configuration set whenever you open the bond. The page for mysql_affected_rows() has this to express (my bold):

For UPDATE claims, the affected-rows value automatically is the amount of rows really transformed. Should you specify the customer_FOUND_ROWS flag to mysql_real_connect() when hooking up to mysqld, the affected-rows value is the amount of rows "found" that's, matched up through the WHERE clause.

And from the mysql_real_connect page:

CLIENT_FOUND_ROWS: Return the amount of found (matched up) rows, not the amount of transformed rows.

So, when it comes to what goes on with CLIENT_FOUND_ROWS being set up, the affected rows for:

UPDATE T1 SET C1 = 'dirty' WHERE id = 1

have nothing related to if the information is transformed, only what rows matched up. This is 1 for queries.

However, if CLIENT_FOUND_ROWS was not set, the 2nd query wouldn't really be altering the row (becasue it is already populated with 'dirty') and might have a row count of zero.

Should you wanted the same behavior no matter that setting (only showing changes), you could utilize something similar to:

UPDATE T1 SET C1 = 'dirty' WHERE id = 1 AND C1 <> 'dirty'

MySQL is Acidity-compliant if you are using a transactional storage engine like InnoDB.