我正在构建多租户Web应用程序。
有时候,有多个用户在更新用户表,因此我不得不通过锁定和考虑Web中的延迟与记录竞争来保持某种数据完整性。用户必须有合理的时间来确保文档在更改时不会更改。我选择的时间是10分钟。
我有一个伪锁表,而不是锁定数据库表中的记录。为了修改记录,用户必须在LockTable中成功插入并维护一条记录。如果锁定成功,则用户将获取数据,否则将得到一个错误,并被告知另一用户已将其锁定。保持锁定要求用户对文档进行某些操作,这将导致浏览器至少每10分钟要求服务器更新一次锁定。 10分钟后,另一个用户可以锁定。当拥有锁定的用户提交更新或任何其他操作时,服务器上发生的第一件事就是检查以确保他们仍然拥有锁定
文档以经典方式设置,带有标题表和详细信息表。
简化示例:
假设一个订单有一个OrderHeader记录和多个OrderDetails记录。用户已收到部分订单,并希望更新订单状态和收到的数量。
用户从服务器发送请求订单列表的请求。 用户选择文档“ 27”
浏览器将请求发送到服务器以锁定和检索文档“ 27”。
在服务器上
GetOrderDocument(Document & user information)
{
Insert into LockTable USER:=CurrentUser TABLE:=ORDERHEADER RECORD:=27 LockTime:=Now
if ( lock insert fails) // document is already locked
{
GetLock TABLE:=ORDERHEADER RECORD:=27 // read the current lock
if( Now - LockTime > 10 min) // if lock is older than 10 min
{
take over lock by changing USER: and Locktime
}
else
{
return message to browser "Document is locked by <user name>"
}
}
/* user now has the lock*/
Select document header& details with LockTime into a Json
Return Json
}
在浏览器用户上进行更改,然后按保存
浏览器
SaveData()
{
collect data to update
Set up ajax call and send update data and the LockTime last received from the server
}
在服务器上
UpdateData(Changes, OldLockTime)
{
Check DBLockTime in DB with OldLockTime
if ( DBLockTime == OldLockTime )
{
Update LockTime with LockTime:=Now
}
else
{
message="you have lost the document lock. changes not saved"
return message
}
Update records as required
return event status and new LockTime
}
冲洗并重复。 当用户处理完文档后,将向服务器发送请求以删除LockTable记录。如果失败,则最多只能持续10分钟。
这可以解决在Web上修改文档的延迟问题,并确保用户有合理的时间进行工作,但要确保用户走开或互联网死亡时,记录将可用。 / p>
现在我需要再添加一些东西。
有时,服务器需要检查和更新除主文档之外的其他表中的另一条记录。该记录是一个计数器记录,需要先读取然后递增。服务器只需要在其他文档更新时使用该记录,但是该计数器的读取和更新必须是原子的,并且与主文档在同一事务中进行。
在这种情况下,我要做的是
在服务器上
UpdateData(Changes, OldLockTime)
{
Check DBLockTime in DB with OldLockTime
if ( DBLockTime == OldLockTime )
{
Update LockTime with LockTime:=Now
}
else
{
message="you have lost the document lock. changes not saved"
return message
}
set haveLock = false
loop 10 times
/* trying to insert new lock record in Locktable*/
if( GetCounterRecordLock == false)
sleep 1 second
else
{
haveLock = true
break out of loop.
}
endloop
if ( haveLock == false)
return error message indication update failure
Start transaction
read and update counter table.
Update main document records as required
commit trans.
delete CounterRecordLock from LockTable
return event status and new LockTime
}
我知道锁定记录的工作原理非常好。那已经被测试到死了。
我担心的是试图获得第二个锁作为计数器记录。
是否要获取10次并在两次尝试之间等待1秒钟才是正确的方法?欣赏别人的想法。
谢谢。