I have been reading about database isolation level and TransactionScope here, here and here, but none seems to answer my question. The problem I have is a simple read and write problem.
A concrete scenario is describe below
- process1 reads the initial state : ReadyForShipment
- process2 reads the state: ReadyForShipment
- process1 mutates the state to Canceled and commits its transaction
- process2 mutates the state to Shipped, which is invalid, because a Canceled item should not be Shipped.
Prcess1 and process2 does not communicate with each other and I am hoping for a database level solution to keep it that way. I know that Isolation level Serializable solves the problem because the read lock acquired in step2 prevents step3 from succeeding.
In order to find a less restrictive isolation level, I've also read up on ReadCommitted and row versioning. According to this text from here
Locking and row versioning prevent users from reading uncommitted data and prevent multiple users from attempting to change the same data at the same time. Without locking or row versioning, queries executed against that data could produce unexpected results by returning data that has not yet been committed in the database
It seems to imply that row versioning could be a solution for the read and write problem. In step4, with row versioning, database should be able to detect that it is trying to change a row whose version has already been changed since the read in step2. But my experiment proved that this is not the behavior. With ReadCommited isolation and READ_COMMITTED_SNAPSHO of the database set to ON, step4 succeeded with the state updated to Shipped.
My question is, besides isolation level Serializable, is there another database level solution to the read and write problem describe above?