首页 > 解决方案 > 带锁表的多租户..请检查我的方法

问题描述

我正在构建多租户 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 秒是正确的方法吗?别人的想法是值得赞赏的。

谢谢。

标签: c#mysql

解决方案


推荐阅读