Transactions allow us to treat a composite action as an atomic one. A benefit of transactions is that they compose safely, without risk of deadlock. Unfortunately, transactions are a mediocre basis for concurrency control at both large and small scales. Some points:
- Large transactions have high risk of disruption and rework. By nature, transactions must be limited to small-scale tasks.
- Transactions aid us by increasing the granularity of our commands. If we keep them small, we still face all the same concurrency issues once our commands cross multiple transactions.
- A compositional system requires distributed transactions, i.e. such that a client can invoke two services in a single transaction. Without this, we’re forced to provide a monolithic service and database to serve all client requirements.
- If we use distributed transactions, it becomes difficult to control their scope. We can introduce transaction barriers (i.e. that delay messages until commit) but we can only control those in a small subset of the application.
- Transactions are not very robust in a security sense. I.e. they are very vulnerable to denial of service attacks. We can mitigate this with priority, but administrators for different services in a system are unlikely to agree with your priority requests.
- Transactions don’t integrate well at the edges – sensors, actuators. Sensors often provide continuous data streams, and are subject to data fusion, so no clear transactional boundaries exist. Actuators cannot generally ‘undo’.
- The need to redo work makes the transactional model invalid for hard real-time systems.
I pursued transactions as a basis for concurrency control for a couple years before developing RDP. One example of my efforts is transactional actors model. But I became disillusioned and embittered with transactions as they caused headaches for scalable semantics and implementation, proved infeasible for embedded real-time control systems, and failed one pseudocode test after another. I believe I’ve offered transactions a fair trial.
Transactions are not terrible. I would never have pursued them if they were entirely ineffective. In terms of scalability and security and composition, transactions are certainly superior to mutexes, and compare well to promise pipelining models.
But transactions are not sufficient for my vision.
I have since returned to temporal models, where time is modeled explicitly. I initially disregarded temporal models due to perceived difficulty with clock drift, performance, and consistency at scale. However, I’ve since found that explicitly modeling delay can both allow drift for performance and mask drift for consistency.