I am looking at a codebase where a developer never uses SQL transactions i.e. each update/insert into the SQL database is an atomic operation.
I believe the codebase would benefit from transactions. I was looking online today and in one Stackoverflow question an answerer says: “In some situations it is better to have a partial update rather than none at all”. Is there any truth in this? I suppose it depends on the problem domain to some extent.
6
It depends not just on the problem domain, but also on technical considerations. Basically, it comes down to the simple question: “Will there be unacceptable problems when a partial update happens?” Some examples:
- Transfering money from one account to another. A partial update is completely unacceptable for domain reasons.
- Adding a vote to an online poll and incrementing a result count (which is only for display, with the final result being recalculated from the vote table). A partial update is probably acceptable.
- Adding something to an n:m relationship. A partial update would result in an inconsistent state where you have either an entry that is not connected, or a connection without a matching entry. This is unacceptable for technical reasons – you’d get an error whenever that entry is encountered and it would likely be impossible to fix this error within the system.
- A hardware unit that sends batches of sensor data to be stored. Adding only some of the entries of a batch is probably better than losing all of it.
Honestly, it’s really rare for partial updates to be tolerable.
2
From the database perspective, frequent commits are often used to prevent records being unreadable by other sessions as they are locked by the updating session.
However this varies by RDBMS. Oracle has always had an MVCC system that prevented readers from blocking writers and writers from blocking readers, so it is not a problem there for instance.
Over-frequent committing on Oracle is strongly discouraged not only because it can leave partial transactions in the system but also because a COMMIT requires a synchronous redo log buffer flush which stalls the session (a high level of log_file_sync wait events is symptomatic of over-committing). Redo log buffers are asynchronously flushed every few seconds or when they are X% full anyway, so a longer running transaction may have less work to do during an explicit commit if it is deferred until the end of the business transaction anyway.
9