我有以下情况,使用C#和.NET 4.0。
我需要控制当我加载一组寄存器时,其他用户无法向该组添加新的,直到第一个用户尚未完成处理此数据。这是因为当一个用户添加一个新寄存器时,其数据取决于同一组的所有寄存器的信息。
一个简单的例子(愚蠢的例子,真实案例有点复杂)。我有一个int数组。我想在我的数据寄存器中有一个指向该组的最大int的字段。
Group: (IDGRoup, Name, description...)
Data: (IDData, IDGroup, IDMaxData,...)
如果我有两个用户尝试向该组添加新的int,则该过程如下:
1.-加载小组中的所有号码。
2.-搜索最大数量
3.-使用最大数字的ID设置IDMaxData。
4.-保存iformation。
问题是,如果两个用户同时加载,并尝试添加新的int,如果其中一个用户将添加新的最大组号,则另一个用户无法将正确的ID设置为最大数量,因为他没有加载新的最大数量。因此,信息不一致,因为此用户将IDMaxData设置为旧的最大数字。
如何确保数据一致?
我正在考虑使用交易。
1.-从Group加载寄存器,ID是我想要的组的ID。如果我使用一个事务,隔离级别可序列化,在我加载组的寄存器的那一刻,第二个用户是阻塞因为他无法加载寄存器。因此,如果第二个用户无法加载组表的寄存器,他将无法添加新的寄存器。
2.-第一个寄存器可以从Data表中加载所有int。他可以确定有所有寄存器,因为第二个用户无法添加新的寄存器(他正在等待),因此他可以将IDMaxData设置为正确数量的保修。
3.-保存并发布数据。
他正在使用的第二个用户,no可以从Group表中加载寄存器,并阻止其他用户。做好工作并释放寄存器。
我怀疑这是否是一个很好的解决方案。我能看到的唯一问题是我阻止了Group表的寄存器,所以如果有人想要更新它的信息,必须等到寄存器释放。但这是一个小问题,因为这个表的信息不会更新。
还有其他选择吗?
感谢。
答案 0 :(得分:1)
您正在描述严格锁相的技术,其中不允许任何事务开始,直到最后一个trxn被提交。但我们也有其他技术。使用简单的锁相。
before any write the trxn must perform the read.
the trxn must acquire the read or write lock before performing any change on data item.
no two trxn can take write lock on same item.
您还可以使用时间戳排序(TO)技术。
有关详细信息,请查看此ppt - > Concurrency contol
答案 1 :(得分:1)
正如Arpit的Concurrency control link所说,Serializable
的隔离级别可以避免Phantom Read
问题。因此,对于您的问题,它实际上是一个Serializable
隔离级别的解决方案。但隔离级别越高,并发效率就越低。如何将max int存储到全局静态属性?它基于db初始化,并在应用程序关闭时存储回db。并且在读取或更新时必须对全局静态属性应用锁定。