|
|
|
|
|
by formerly_proven
2063 days ago
|
|
Transactions give varying degrees of "isolation" between them, depending on the database (and its version + configuration). For example, in what SQL would call READ COMMITTED, where transactions will only read data that has been committed, read-modify-write updates are generally bugs. The classic example: - Intent: both transactions deduct 50 money
- transaction 1: SELECT balance FROM account; // = 100
- transaction 2: SELECT balance FROM account: // = 100
- transaction 1: UPDATE account SET balance = 50
- transaction 1: COMMIT
- transaction 2: UPDATE account SET balance = 50
- transaction 2: COMMIT
- Result: balance is 50, but should be 0
With serializabile transactions (not all databases have this, particularly if you look beyond SQL): - Intent: both transactions deduct 50 money
- transaction 1: SELECT balance FROM account; // = 100
- transaction 2: SELECT balance FROM account: // = 100
- transaction 1: UPDATE account SET balance = 50
- transaction 1: COMMIT
- transaction 2: UPDATE account SET balance = 50
- transaction 2: COMMIT -> Fails, needs to retry
- transaction 2b: SELECT balance FROM account: // = 50
- transaction 2b: UPDATE account SET balance = 0
- transaction 2b: COMMIT -> Ok!
- Result: balance is 0
Because this is needed so frequently, databases have calculated updates, basically atomic operations: - transaction 1: UPDATE account SET balance = balance - 50; // values indeterminate
- transaction 2: UPDATE account SET balance = balance - 50; // values indeterminate
- transactions 1,2: COMMIT
- Result: balance is 0
Or, one could lock the rows, like so: - transaction 1: SELECT FOR UPDATE balance FROM account; // = 100
- transaction 2: SELECT FOR UPDATE balance FROM account: // = transaction 2 is stalled until transaction 1 commits or rollbacks
- transaction 1: UPDATE account SET balance = 50
- transaction 1: COMMIT
// transaction 2 can now continue and gets balance = 50
- transaction 2: UPDATE account SET balance = 00
- transaction 2: COMMIT
- Result: balance is 0
And this is just one simple example of the problems you can have concurrently accessing one table, even while using transactions. Not to speak of the issues you can run into when interacting with systems outside a single database, which don't interact with the transaction semantics of the DB.Concurrency is just very non-trivial regardless the abstraction. |
|
I want to focus entirely on your first example.
Let me ask you: What is it about your first example that makes you call it transactional? If it behaves as badly as you say, shouldn't it be called a 'method' or a 'procedure'? Because my "fix" for it is to actually use transactions. I suspect your fix would be the same.
Why did you choose to interleave its steps like that, when "Isolation ensures that concurrent execution of transactions leaves the database in the same state that would have been obtained if the transactions were executed sequentially."
If you're telling it like it is, then I cannot argue with facts. I guess I'll stop using DBs, at least until they figure this stuff out in 1973.