1.场景描述
这是开发中的一个项目,有以下场景:
- 对于一条消息m,有若干个接收者(r1, r2)。
- 接收者(假设为r1)收到消息后,发送确认消息。
- 收到r1的确认消息后,服务器从消息m的接收者中删除对应的接收者(r1)。
- 服务器检查消息m的接收者队列,如果为空,则删除消息M
在极偶然的情况下,竟然发现,当r1,r2都发出了消息确认,而消息M的数据库记录中的接收者队列也确实是空,但是消息M竟然没被删除!
2.伪代码
服务器关于接收确认消息的处理伪代码大概如下:
// 开启事务
begin_transaction()
// 从db中找到消息m
// select * from M where id = some_id
m = find(some_id)
// 从db中找到消息m的接收者
receivers = find_receivers(m)
// 从db中删除消息m的接收者r
del_receiver(m, r)
// 从receivers中删除该接收者r
receivers = remove(receivers, r)
if (receivers.empty()) {
// 如果接收者队列为空,即没有接收者了,则删除消息m
del_m(m)
}
commit_transaction()
3.疑问
如果简单的把事务当成锁的话,那上面的逻辑无懈可击,因为最后一个确认消息到达后,消息的接收者队列必然会清空,消息肯定会被删除。但残酷的现实表示,不一致状态还是出现了:消息的接收者队列是空的,但是消息没有被删除。
发生这种情况的唯一解释就是,r1,