I'm comparing Saga and Two-Phase Commit
My analysis about 2PC is if in prepare phase I persist the data in a pending state, I could avoid a lockin in my transaction and in the final phase commit my changes.
Obviously the cost is 2x against Saga Pattern, but in some cases 2PC could be more interesting than Saga.
For example: As a part of a transaction an email is sent, with Saga is not possible revert this, case there is a fail, but with 2PC this is possible (Let's assume this is important for my bussiness).
My finally doubt is, is there a pattern like 2PC following what I wrote above? Or no, there is no other pattern is just an adaptation of 2PC.
PS: I read some articles and researched another questions before public this.
The primary advantage of the two-phase commit protocol / distributed transactions is the fact that the programming model is more or less equivalent to that of local transactions except for the enlistment of additional resources and the final prepare/commit phase (which is often handled by frameworks). ACID properties still fully apply and data consistency is handled by the infrastructure, not the developer.
A major disadvantage is the complexity of the two-phase commit protocol in terms of infrastructure requirements and in case of component failure. A distributed transaction manager is required so that decisions are written to stable storage and commits/rollbacks can be executed by the TM in case of component failure. Prepared transactions can involve locks that are held for as long as the transaction has not been committed and/or rolled back. This is particularly problematic because those so-called in-doubt transactions have to be handled by the TM, which can incur significant delays that might affect other (even local) transactions and/or database housekeeping background processes.
Performance is another aspect. Depending on the write traffic, the transaction manager that needs to maintain a transaction log, can become a bottleneck.
System backups become more challenging as well. The whole idea of distributed transactions is that the view of the database remains consistent. In case of backups, creating backups of each database involved won't allow you to recreate that unless you make sure that a restore of each database is done to a specific point-in-time based on a timestamp, or better, a local transaction ID. This is usually called distributed point-in-time recovery and involves blocking all new distributed transactions, reading the current transaction ID from each individual database and storing that information along with the individual backups. At restore time, the database can be restored to the point-in-time based on the recorded transaction ID. Additionally, the TM transaction log must be part of the backup strategy.
The Saga pattern does not provide an infrastructure for guaranteeing consistency, the programming model has to take consistency concerns into account. In case of distributed transactions, a financial transaction would involve one distributed transaction that subtracts the amount in database A and adds the amount in database B, the result of which would become visible with the commit of a distributed transaction. In case of Saga, the same financial transaction might create a pending transaction record in database A and a pending transaction record in database B, the result of which would become visible with two individual transactions that confirm those transaction records once the service of database B successfully reports execution completion to service A. Alternatively, a dedicated orchestrator could process the transaction by communicating to each individual service. A rollback in Saga triggers compensating transactions that undo work that was already committed.
In many ways, Saga simulates distributed transactions by requiring the programming model to deal with consistency concerns. The database schema has to take consistency into account by associating status or version information with database objects/rows to create a fully or eventually consistent database view again. All that has to be done by the developer (or a framework, if available), not the database infrastructure.
What Saga buys is flexibility because each individual consistency concern can be addressed based on the actual consistency constraints required. Total consistency is not normally required in every single use case there is. This could mean higher performance and scalability as the consistency requirement can be scaled as well and a centralized TM is usually not involved. It also buys flexibility in terms of infrastructure because the components involved do not have to support distributed transactions (most NOSQL databases do not). This directly affects scalability as the choice of database affects the scalability of resulting system. Backups can usually be created without involving other databases because the individual systems already have to deal with inconsistencies at a much higher level.
The tight coupling required by distributed transactions can severely limit scalability, performance and availability. The larger the service, the less likely it is that distributed transactions can be used to guarantee consistency across all components. Many large-scale deployments have hundreds of microservices that are mostly independent from each other and merely cooperate using a well-defined API. The availability of service A does not necessarily affect service B, which is a good thing. Alternatively or in addition to that, the data those microservices operate on is often partitioned based on well-defined criteria (e.g. customers a-d, ...) to create instances that can actually be managed as one unit and allow for horizontal scalability and high availability. Using distributed transaction across the whole service would kind of defeat the purpose.
Concerning the specific scenario you mentioned: sending an e-mail represents an action that affects external systems and cannot be rolled back. Therefore, in case of both, Saga and distributed transactions, the e-mail can only be sent once all other steps succeeded.