c# - 带锁表的多租户..请检查我的方法
问题描述
我正在构建多租户 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 分钟。
这解决了通过网络修改文档的延迟问题,并确保用户有合理的时间来完成他们的工作,但确保如果用户离开或他们的互联网中断,记录将变得可用。
现在我需要在混合中加入更多的东西。
有时,除了主文档之外,服务器还需要检查和更新不同表中的另一条记录。该记录是需要读取然后递增的计数器记录。服务器仅在其他文档更新时需要此记录,但此计数器的读取和更新需要与主文档在同一事务中是原子的。
在这种情况下我要做的是
在服务器上
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 秒是正确的方法吗?别人的想法是值得赞赏的。
谢谢。
解决方案
推荐阅读
- rust - 递归声明模块公开的最简单方法
- r - 将javascript函数作为参数传递
- java - 在给定约束的最小移动中将数组减少到 0
- html - 你能建议我正确的语法吗?
- ruby-on-rails - 在添加/删除 ENV 变量时,Elastic Beanstalk 导致我的 Rails 6 应用程序预编译资产中断
- git - git clone repo A 到新的 repo B,同时仍然从 repo A 获取更新
- reactjs - 为 React 钩子计算调整大小的新宽度
- node.js - Node.JS - 如何在控制器中使用清理
- wix - 如何正确删除使用 VSTO 编码的 Office/Outlook 加载项?
- javascript - 比较数组中的值,如果任何值匹配,则增加第一个数组中的值