1. Isolation
Isolation은 DBMS 특성인 ACID 중 하나로 "트랜잭션이 다른 트랜잭션에 영향을 줘서는 안 된다"는 뜻이다. DBMS에서는 각기 다른 Isolation level를 제공하여 이러한 특성을 만족시켜준다. Isolation은 Trade-off가 있다. 즉 Isolation Level이 높을수록 DBMS 성능이 떨어진다는 것이다. (고립을 시킬수록 동시에 Transaction을 수행하는 Connection 수가 줄어들기 떄문에 성능이 당연히 떨어질 것이다.) 그러므로 무조건 높은 Isolation을 사용하기보다는 자신의 서비스 특성에 맞는 Isolation level를 선택해야한다.
2. Isolation Level
ANSI에서는 4가지 트랜잭션 레벨을 제공합니다. 각각에 대해서 정리해보겠습니다.
2-1) Uncommited Read
Uncommited Read는 현재 그 데이터가 write 한후 commit 되어있는 상태이든지 아니든지 read를 허락하는 level입니다. (단 write는 허락되지 않습니다). 이를 위해 Exclusive write lock를 사용합니다. 이로 인해 lost update는 허용 하지 않지만, dirty read 즉 커밋하지 않은 데이터를 읽었을때 그 트랜잭션이 롤백되어서 실제 데이터와 다른 경우가 발생할 수 있습니다. 실제로는 거의 사용되지 않는 레벨이라고 합니다.
Uncommitted Read, or dirty read, lets a transaction read any data currently on a data page, whether or not that data has been committed. For example, although another user might have a transaction in progress that has updated data, and that transaction is holding exclusive locks on the data, your transaction can read the data anyway, and possibly take further actions based on the values you read. The other user might then decide to roll back his or her transaction, so logically, those changes never occurred. Although this scenario isn't desirable, with Uncommitted Read you won't get stuck waiting for a lock, nor will your reads acquire share locks that might affect others.
2-2) Commited Read
Commited Read는 SQL Server에서 사용하는 default isolation 레벨로 Dirty Read를 막을 수 있습니다. 데이터 Read를 할 때 반드시 commited 된 데이터만 read할 수 있습니다. 위에 그림에서와 같이 update를 한 후 2번에서 read를 할려고 하면 락이 걸려서 접근할수 없게 됩니다. 하지만 commited read는 unrepeatable read 문제를 해결하지 못합니다.
Committed Read is SQL Server's default isolation level. It ensures that an operation will never read data another application has changed but not yet committed. Because you can never read uncommitted data, if a transaction running with Committed Read isolation revisits data, that data might have changed, or new rows might appear that meet the criteria of the original query. Rows that appear in this way are called phantoms.
2-3) repeatable read
repeatable read는 read를 한 데이터에 대해서 write하는 것을 허용하지 않습니다. 또한 write 하고 있는 트랜잭션이 있으면 모든 write,read 트랜잭션을 허용하지 않습니다. repeatable read는 unrepeatable read와 dirty 둘다 막을수 있지만 phantom read는 허용합니다.
If you want the read operations to be repeatable, choose the third isolation level. The Repeatable Read isolation level adds to the properties of Committed Read by ensuring that if a transaction revisits data or if a query is reissued, the data will not have changed. In other words, issuing the same query twice within a transaction won't pick up any changes to data values that another user's transaction has made. No other user can modify the data that your transaction visits as long as you have not yet committed or rolled back your transaction.
2-4) Serializable
직렬화 즉 말 그래도 한줄로 서서 순서대로 처리하는 상황입니다. 어떠한 동시성도 허용하지 않고 한번에 한 트랜잭션만 허용합니다. 이로 인해 phantom read 또한 해결할 수 있습니다.
The Serializable isolation level ensures that if a query is reissued, no data will have changed and no new rows will appear in the interim. In other words, you won't see phantoms if the same query is issued twice within a transaction. Rerun the example from the Repeatable Reads section, inserting a row with a col1 value of 35. But this time, set your isolation level to SERIALIZABLE. The second connection will block when you try to do the INSERT, and the first connection will read exactly the same rows each time.
3. 그럼 어떤 걸 골라야할지?
어디까지나 권고사항이며 일반적인 경우를 가정한 상황입니다.
1) read uncommited는 dirty read를 허용하는 매우 위험한 레벨입니다. 사용하지 않는게 좋습니다.
2) Serializable은 DB 성능에 매우 심각한 영향을 줍니다.(한번에 한 트랜잭션만 허용하니) 또한 Phantom read는 보통 문제를 일으키지 않으므로 이것 또한 보통 사용하지 않는게 좋습니다.
3) 그럼 read commited와 repeatable read가 남습니다. 둘의 차이는 unrepeatable read를 허용할지 안할지인데요. 자신의 서비스에 맞는 단계를 고르시면 될거 같습니다. 참고로 mysql의 엔진인 InnoDB는 default로 repeatable read를 사용하고 있다고 합니다.
참고 : www.itprotoday.com/sql-server/transaction-isolation-levels
www.youtube.com/watch?v=xR70UlE_xbo