我有两个数据源:遗留数据库(Web服务)和数据库数据源。现在,当我处理请求时,我对两者都进行了更改。如果出现错误,我想回滚它们。
try
{
legacy.Begin(); db.Begin();
legacy.MakeChanges(); db.MakeChanges();
}
except (Exception)
{
legacy.Rollback(); db.Rollback();
}
问题是,如果旧版在回滚期间抛出(即网络错误)怎么办? db.Rollback()将不会被执行。反之亦然。 我看到的解决方案是:
legacy.Begin();
try
{
db.Begin();
try
{
legacy.MakeChanges(); db.MakeChanges();
}
except (Exception)
{
db.Rollback();
throw;
}
}
except (Exception)
{
legacy.Rollback();
throw;
}
可以接受吗?有更好的解决方案吗?
答案 0 :(得分:1)
您正在有效地推出自己的两阶段提交事务。一个完全强大的解决方案需要两个资源的合作,通常最好使用支持2PC的事务管理器。
这里的根本问题是你没有保护自己的应用程序失败(他扮演事务管理器的角色),因此无法保证你可以回滚那些遗产。 考虑一下你的app即将调用legcacy.Rollbock()的失败。你现在没有记录你正处于“交易”的中间,所以当你的应用程序回来时,你没有理由去执行该回滚。
可能的方法:
1)。使用true 2PC,这只有在您的WebSerice具有事务功能(技术上可行但实际上不太可能)时才有可能。
2)。容忍一些不一致的风险。许多系统实际上无意中这样做了,
3)。尝试恢复你想要的恢复但接受它可能会失败。添加某种形式的审计跟踪,允许检测不确定的结果,从而允许稍后手动补丁。因此,您可以添加一些审计日志记录,以便您检测mismtached活动。这可以看作是一种非常手动的2PC方法。