你好
我想知道在3层应用程序中实现并发控制的最佳方法?首先可以想到的是:
基于这种情况,锁应该同时引用使用该记录锁定的记录和客户端。
客户端必须定期向服务器发送保持活动的消息。“保持活着”用于释放锁定的记录,以防客户在编辑操作中丢失。
我将使用Delphi与数据with。也许这是一个新手的问题,但我必须问!
发布于 2011-03-11 00:27:04
我正在基于jachguate的乐观并发控制答案来回答在评论中提出的一个问题。
我更喜欢尽可能地使用OCC,因为实现更容易。我将讨论使用对象持久化框架的三层应用程序。我的预测方案有三个层次:
这的优点是,大多数情况下,低成本的OCC路径是采取的。对于经常发生的事情,但在低争论的情况下,好处是重大的。想一想仓库中的产品跟踪--产品总是在移动,但很少同时移动相同的项目,当它们同时移动时,解决问题很容易(剩余的数量=原始的减去我的删除和您的删除)。对于产品被重新定位的复杂情况,在产品运输过程中锁定产品可能是有意义的(因为这反映了实际情况)。
当您必须回到锁定状态时,能够通知两个用户并拥有一个通信通道通常是有用的。当锁可用时,至少通知想要锁的用户,最好允许他们向锁持有人发送消息,甚至可能允许他们强制锁。然后通知锁输家“乔·史密斯拿走了你的锁,你失去了你的改变”。让办公室政治来解决这一问题:)
我通常通过用户投诉来驱动回退过程,而不是通过错误报告。如果用户抱怨他们在某一特定过程中经常丢失编辑,请更改它。如果用户抱怨记录锁定得太频繁,您将不得不重构您的对象映射,以增加锁定粒度或进行业务流程更改。
发布于 2011-03-10 23:01:56
我设计我的应用程序时考虑到了一个乐观并发控制,在用户想要编辑它时没有锁定任何记录,也没有试图控制并发性。
重要的计算和更新是在服务器端(应用程序或数据库)在处理客户端应用的更新时设置适当的内置数据库锁定功能之后完成的。DataSnap自动事务回滚防止这些锁在发生故障时阻止其他并发用户。
使用DataSnap,您可以通过为您的字段适当使用ProviderFlags来防止两个用户编辑冲突时的数据丢失。为要自动检查的任何字段设置pfInWhere,使其在编辑/删除时具有与读取记录相同的值。
此外,当冲突发生时,您可以在Application (提供程序OnUpdateError事件)、客户端(TClientDataSet OnReconcileError事件)或甚至要求用户进行适当的冲突解决(查看新项存储库中的ReconcileErrorDialog )时进行编程反应。
同时,IMHO避免了维护锁列表、客户列表、每个客户端列表的锁、保持活跃的消息、健壮的应用程序服务器故障恢复以及所有可能出现的故障--您将以更干净和更好的解决方案结束--所需的复杂性。
发布于 2011-03-10 23:27:13
千斤顶给出的方法很好,而且可能更好,但是如果您确实想实现这个方法,您将需要在服务启动时在服务器上创建一个TThreadList。使用TThreadList,因为它是线程安全的。您可以在每个表上设置TThreadList,以便将导航列表的性能影响降到最低。要控制锁定的内容,需要创建一个对象并将其传递给列表
TLockedItem = class(TObject)
public
iPK: Integer;
iClientID: Integer;
end;要执行实际的锁定,您需要这样的操作:
function LockItem(pPK, pClientID: Integer): Boolean;
var
oLockedItem: TLockedItem;
oInternalList: TList;
iCont: Integer;
bExists: Boolean;
begin
bExists := False;
if (Assigned(oLockedList)) then
begin
oInternalList := oLockedList.LockList;
try
if (oInternalList.Count > 0) then
begin
iCont := 0;
while ((not bExists) and (iCont < oInternalList.Count)) do
begin
oLockedItem := TLockedItem(oInternalList[iCont]);
if (oLockedItem.iPK = pPk) then
bExists := True
else
Inc(iCont);
end;
end;
finally
oLockedList.UnlockList;
end;
if (not bExists) then
begin
oLockedItem := TLockedItem.Create;
oLockedItem.iPK := pPK;
oLockedItem.iClientID := pClientID;
oInternalList := oLockedList.LockList;
try
oInternalList.Add(oLockedItem);
finally
oLockedList.UnlockList;
end;
end;
end;
Result := bExists;
end;这只是你所需要的一个想法。您必须使用类似的逻辑来执行解锁方法。您可能需要一个客户端列表,该列表将保留每个客户端持有的每个TLockItem的点,以防失去连接。这不是一个明确的答案,只是一个方向上的推动,以防你想要实现这个方法。
祝好运
https://stackoverflow.com/questions/5266514
复制相似问题