What's wrong with this picture? repetition = Repetition.find(2) repetition.count = repetition.count + 100 repetition.save SELECT "repetitions".* FROM "repetitions" WHERE "repetitions"."id" = 2 LIMIT 1 (got count = 201) UPDATE "repetitions" SET "count" = 301 WHERE "repetitions"."id" = 2 SELECT "repetitions".* FROM "repetitions" WHERE "repetitions"."id" = 2 LIMIT 1 (got count = 201) SELECT "repetitions".* FROM "repetitions" WHERE "repetitions"."id" = 2 LIMIT 1 (got count = 201) UPDATE "repetitions" SET "count" = 301 WHERE "repetitions"."id" = 2 UPDATE "repetitions" SET "count" = 301 WHERE "repetitions"."id" = 2 Don't transactions prevent this
from happening?
BEGIN; LOCK TABLE repetitions IN ACCESS EXCLUSIVE MODE; COMMIT; BEGIN; SELECT "repetitions".* FROM "repetitions" WHERE "repetitions"."id" = 2 LIMIT 1 FOR UPDATE; UPDATE "repetitions" SET "count" = 101 WHERE "repetitions"."id" = 2; COMMIT; Repetition.transaction do repetition = Repetition.lock.find(2) repetition.count += 100 repetition.save! end UPDATE "repetitions" SET count = count + 1 WHERE "repetitions"."id" = 2; c = ActiveRecord::Base.connection_pool c.with_connection do |con| con.exec_query("UPDATE repetitions SET count = count + 1 WHERE repetitions.id = 2;") end Other Solutions
* SERIALIZABLE transactions
* Optimistic Locking
* Advisory Locks