【问题标题】:Best way to ensure Item can only be used by 1 user确保项目只能由 1 个用户使用的最佳方法
【发布时间】:2018-12-11 12:59:01
【问题描述】:

我有一个带有两个主表(所有任务)和(进行中)的 Web 应用程序。当您从(所有任务)打开任务时,该项目将移至(进行中)。现在,如果不同电脑上的用户同时打开任务,它会重复。

在你们的意见中,确保不会发生重复的最佳方法是什么。

我目前有一列,如果未处理,则为 0,如果已处理,则为 1,但这仍然给出了 2-3 秒的时间段,可以同时从两台电脑打开任务。

我已经研究了 guid 并使用 sql 事务,尽管我读过这会减慢速度

我希望这是有道理的,我的伙计们

提前致谢

一个小恶魔

【问题讨论】:

  • 在数据库中保存新记录时会发生重复。确保在不需要时不要保存记录。
  • 您应该检查行是否已经存在,并在此基础上执行操作或丢弃它。
  • 使用事务,如果你正确使用它们,它们不应该减慢速度。当第一个用户的事务完成时,第二个用户将等待 2-3 秒,这应该是唯一的减慢速度。您还可以添加一个“进行中”标志,如果它是 0,则在事务中将其设置为 1,然后在处理完成时将其设置回 0,也在事务中。现在第二个用户只会被延迟一瞬间然后会看到“进行中”标志已设置并且无法获取任务?
  • @RichardHansell 所以我目前正在使用一个正在进行的标志,但它允许两个人可以打开相同的任务的 2 秒间隙。我将尝试交易,看看它如何影响性能。谢谢人:)
  • 对不起,我没有说清楚。一旦同一任务设法被两台电脑同时打开,在该任务上输入的所有数据都将在数据库中复制,不一定是任务本身。所以我需要一个有效的标志。

标签: javascript c# sql api


【解决方案1】:

为目标表提供一个包含源表主键的列,并对其施加唯一性约束。或者,如果可能,只需给它们相同的主键。

例如,如果您的AllTasks 表的主键为TaskID,则在您的InProgress 表中也放置一个TaskID 列,并对其施加唯一性约束。如果两个用户尝试复制同一条记录,则第二条记录将违反约束,插入将失败。

【讨论】:

    【解决方案2】:

    这并不是一个解决方案,只是一个帮助您入门的快速框架:

    CREATE TABLE #tasks (task_id INT, other_stuff VARCHAR(50), held BIT);
    INSERT INTO #tasks SELECT 1, 'My Test Task', 0;
    CREATE TABLE #work_queue (task_id INT);
    
    --User #1 puts a task onto the work queue
    BEGIN TRANSACTION;
        UPDATE #tasks SET held = 1 WHERE task_id = 1 AND held = 0;
        --Did we get it?
        IF @@ROWCOUNT = 1
            INSERT INTO #work_queue SELECT 1;
    COMMIT TRANSACTION;
    
    --User #2 fails to get a handle to the task so nothing is put onto the work queue
    --Note that this can be run asynch from a second session
    BEGIN TRANSACTION;
        UPDATE #tasks SET held = 1 WHERE task_id = 1 AND held = 0;
        --Did we get it?
        IF @@ROWCOUNT = 1
            INSERT INTO #work_queue SELECT 1;
    COMMIT TRANSACTION;
    
    --Task completes
    BEGIN TRANSACTION;
        DELETE FROM #work_queue WHERE task_id = 1;
        UPDATE #tasks SET held = 0 WHERE task_id = 1;
    COMMIT TRANSACTION;
    

    如果用户前来“预订”一项任务,则会出现以下结果之一:

    • 他们通过将保持标志设置为 1 来获得“锁定”,之前它是零。因此,任务被预订并添加到进行中的表中(在我的示例中为工作队列);
    • 他们无法预订任务,因为它已被其他人预订。所以什么都没有发生。

    如果您要同时从多个用户运行“预订阶段”,那么只有一个用户可以获得任务,但“放慢速度”的方式很少。


    另一种(更好的?)处理方式是存储正在运行作业的用户的 user_id,而不是 BIT 标志。现在您知道谁拥有这份工作,而不是简单地知道有人“预订”了它,所以您无法得到它?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-17
      • 2010-10-19
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 2014-11-28
      • 2017-10-31
      • 1970-01-01
      相关资源
      最近更新 更多