【问题标题】:Could I just always flush a write ahead log instead of implementing a Two-Phase Commit protocol?我可以总是刷新一个预写日志而不是实现一个两阶段提交协议吗?
【发布时间】:2020-09-08 02:21:29
【问题描述】:
我无法理解two-phase commit protocol 的部分内容。我完全不明白第二阶段有什么帮助。
据我了解,第二个(完成)阶段可能会失败,就像我们只有一个阶段一样。我们是否需要第二阶段来确保在刷新预写日志时捕获磁盘故障?如果是这样,是否需要不断刷新预写日志并避免缓慢的网络通信和延迟?
【问题讨论】:
标签:
database
transactions
commit
distributed-computing
distributed-transactions
【解决方案1】:
两阶段提交协议是跨多个不同实体的事务。
考虑一个例子
姓名:用户 1,余额:100 美元
姓名:User2,余额:$200
现在假设在一笔交易中,您将 50 美元从用户 1 转移到用户 2。现在交易余额应该变成了
姓名:User1,余额:50 美元
姓名:User2,余额:250 美元
因此有两个步骤
void Transaction(int amount)
{
User2.Add(amount);
User1.Subtract(amount);
}
现在如果金额为 150 美元,在这种情况下 User1.Subtract(amount) 将失败(因为余额不能为负数),而 User2.Add(amount) 会成功。
要执行各种验证,需要“投票”阶段。 “提交”阶段存在以原子方式说是/否来完成事务。两相的非常简单的伪代码是:
bool Perform_Two_Phase_Transaction(int amount)
{
var addVote = User2.VoteFor_Add(amount);
var subtractVote = User1.VoteFor_Subtract(amount);
if(addVote && subtractVote)
{
var addCommit = User2.Commit();
var subtractCommit = User1.Commit();
if(addCommit && subtractCommit)
{
return true;
}
if(addCommit)
{
User2.Rollback();
return false;
}
if(subtractCommit)
{
User1.Rollback();
return false;
}
}
}