# Commit de tres fases

El protocolo commit de tres fases, también conocido por las siglas 3PC (del inglés 3-Phase Commit), es un protocolo de consenso distribuido que permite a todos los nodos de un sistema distribuido ponerse de acuerdo para hacer commit a una transacción. Típicamente es usado en Bases de datos distribuidas.
Resuelve el problema de confiar totalmente en el funcionamiento correcto en el coordinador del algoritmo de dos fases. Para ello añade una fase extra entre las dos fases del algoritmo de dos fases. En ella el coordinador envía un mensaje de preparado para commit a todos los nodos con la decisión de si hay que hacer commit o no. Si el coordinador obtiene una respuesta de todos los nodos entonces pasa a la fase de commit.
Con este método, como cada nodo tiene la decisión almacenada independientemente, si el coordinador o cualquier otro nodo cae la ejecución de la transacción no es afectada. Esto puede ser aprovechado por ejemplo por un coordinador de repuesto que puede continuar con el protocolo.
Al contrario del protocolo de commit de dos fases (2PC), el 3PC no es bloqueante. Específicamente, 3PC sitúa un límite superior de la cantidad de tiempo requerido antes de que una transacción haga el commit o aborte. Esta propiedad asegura que si una transacción dada está intentando hacer commit vía 3PC y mantiene algún recurso bloqueado (locking), puede liberar los bloqueos después del límite de tiempo (timeout).
El protocolo 3PC fue originalmente descrito por Dale Skeen y Michael Stonebraker en su artículo "A Formal Model of Crash Recovery in a Distributed System." En este trabajo, ellos modelaron 2PC como un sistema de "máquina de estado finito no determinista" y probaron que no es resistente a un fallo aleatorio de un único nodo. La observación básica es que en 2PC, mientras un nodo está en el estado de "preparado para commit", el otro puede estar tanto en el estado de "commit" como en el de "abortar". A partir de este análisis, desarrollaron 3PC para evitar dichos estados y por tanto ser resistente a dichos fallos.

## Descripción del protocolo

El algoritmo está basado en la existencia de un coordinador, liderando la transacción, y al resto de nodos, a los que se llama participantes que son dirigidos por el coordinador

### Funcionamiento del coordinador

* El coordinador recibe una solicitud de transacción. Si hay un fallo en este momento, el coordinador aborta la transacción (en cuanto se recupere hace la transición por fallo). En caso contrario, el coordinador envía un mensaje de inicio de transacción a los participantes y cambia al estado de en espera.
* Si hay un fallo, timeout, o si el coordinador recibe un mensaje de no se iniciará la transacción en el estado de en espera, el coordinador aborta la transacción y envía un mensaje de abortar a todos los participantes. En caso contrario el coordinador recibirá mensajes de puede comenzar la transacción desde todos los participantes dentro de la ventana de tiempo, y por tanto envía mensajes de commit a todos los participantes y cambia al estado de preparado.
* Si el coordinador tiene éxito en el estado de preparado, cambiará al estado de commit. Sin embargo si el coordinador se pasa de tiempo mientras espera un reconocimiento de un participante, abortará la transacción. En el caso de que todos los reconocimientos son recibidos, el coordinador cambia también al estado de commit.

### Funcionamiento de un participante

* El participante recibe un mensaje de inicio de transacción desde el coordinador. Si el participante está de acuerdo, contesta con un mensaje de se iniciará la transacción(OK) al coordinador, y cambia al estado de en espera. En caso contrario envía un mensaje de no se iniciará la transacción y aborta. Si hay un fallo, cambia al estado de abortar.
* En el estado de en espera, si el participante recibe un mensaje de abortar desde el coordinador, tiene un fallo, o se pasa de tiempo esperando un commit, aborta. Si el participante recibe un mensaje de preparado, contesta con un mensaje ack y pasa al estado de pendiente.
* Una vez en el estado de pendiente, al recibir un mensaje de commit, hace el commit. En caso de fallo o de timeout también hace commit.

## Desventajas

La principal desventaja de este algoritmo es que no puede recuperarse en el caso de que la red sea segmentada de alguna forma. Dicho de otra forma, si la red de nodos fueran separadas en dos mitades, cada mitad continuaría a su aire.