Lost Update는 두 개의 트랜잭션이 동일한 데이터를 동시에 수정하려 할 때, 한 트랜잭션의 변경사항이 다른 트랜잭션에 의해 덮어쓰이는 현상입니다. 이로 인해 데이터의 일관성이 깨질 수 있습니다. 예를 들어, 두 트랜잭션이 동시에 같은 계좌의 잔액을 읽고 각각 입금과 출금을 수행하면, 결과적으로 한 트랜잭션의 업데이트가 손실될 수 있습니다.
이 문제를 해결하기 위해 MySQL에서는 락킹 리드(Locking Read)를 사용해야 합니다.
락킹 리드는 데이터를 읽을 때, 동시에 다른 트랜잭션이 해당 데이터를 수정하지 못하도록 락을 거는 방식입니다. MySQL에서는 SELECT ... FOR UPDATE 구문으로 이 기능을 구현할 수 있습니다. 이 구문은 데이터를 읽으면서 해당 데이터에 라이트 락을 걸어, 다른 트랜잭션이 동일 데이터를 수정하려고 할 때 대기하게 만듭니다.
SELECT balance FROM accounts WHERE id = X FOR UPDATE;
FOR UPDATE 구문을 사용하여 X의 잔액을 읽으면서 라이트 락을 획득합니다.이 방법을 통해 T1과 T2가 서로 영향을 주지 않으면서 순차적으로 실행될 수 있으며, Lost Update 문제를 방지할 수 있습니다.
MySQL에서 락킹 리드는 가장 최근에 커밋된 데이터를 읽습니다. 예를 들어, T2가 30을 입금한 후 커밋하면, T1이 FOR UPDATE로 X의 잔액을 읽을 때 30이 추가된 최신 잔액을 읽게 됩니다.
SELECT balance FROM accounts WHERE id = X FOR UPDATE;
이 구문을 사용하면, T1은 T2가 커밋한 후에만 실행되어 Lost Update 문제가 발생하지 않습니다.
비슷한 기능이 PostgreSQL에도 존재하지만, 두 시스템 간에는 동작 방식에 차이가 있습니다. PostgreSQL에서는 FOR UPDATE 구문을 사용하더라도 트랜잭션이 롤백될 가능성이 있습니다. 이는 PostgreSQL의 Serializable Isolation Level이 MySQL과는 달리 SSI(Serializable Snapshot Isolation) 기법을 사용하기 때문입니다. 이 기법에서는 커밋 순서에 따라 트랜잭션이 롤백될 수 있습니다.
MySQL에서 Lost Update 문제를 해결하기 위해서는 트랜잭션에서 FOR UPDATE 구문을 사용하여 락킹 리드를 적용하는 것이 중요합니다. 이는 데이터의 무결성을 유지하면서 동시성 문제를 해결할 수 있는 강력한 방법입니다. 또한, MySQL과 PostgreSQL 간의 동작 방식 차이를 이해하고, 이를 바탕으로 적절한 격리 수준을 선택하는 것이 필요합니다.
https://www.youtube.com/watch?v=aL0XXc1yGPs&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe