【问题标题】:SQL Stored Procedure Simultaneously Call IssueSQL存储过程同时调用问题
【发布时间】:2017-05-15 21:36:57
【问题描述】:

我在 sql server 2008 中有存储过程,我的存储过程计算并从表 B 的列中获取最后一个数字“非主键”,然后在该数字上加一个 (+1) 以在下一条语句中使用它相同的存储过程。

我的问题是我有时有重复的号码,我认为这发生在多个用户同时调用存储过程时。这是问题吗,我该如何解决它

我的代码如下:-

DECLARE @ID AS NVARCHAR(10)
SET @ID =   (
                SELECT TOP 1 MyNo
                FROM Employee
                WHERE (
                            (TypeID = @TypeID) AND
                            (Year = @Year)
                      )
                ORDER BY ID DESC
            )

SET @ID = ISNULL(@ID,0) + 1


INSERT INTO Employee (name,lname,MyNo) VALUES (@name,@lname,@MyNo)

【问题讨论】:

  • 不好,你的桌子上应该有PK
  • 这种“自己动手”的身份替换是一种反模式。它充满了错误。为什么哦,为什么要对这个值进行数学运算,然后将其存储在 nvarchar(10) 中?您应该修复您的架构。将列的数据类型更改为 int 并使用标识属性。其他任何事情都会在某个时候遇到问题。
  • 谢谢大家。但这是一个示例代码,而不是实际代码。实际代码是 varcharchar(10) 因为 no 类似于这个 no-year 示例 123-2017 而 123 是我生成它的增量 no,它不依赖于主键。
  • 为什么不添加另一个标识列?
  • @KannanKandasamy 正如我之前提到的,数字的计算取决于许多条件和类型,不能是一个身份

标签: sql sql-server tsql stored-procedures


【解决方案1】:

您可以使用 WITH (TABLOCKX, HOLDLOCK) 语法在事务期间锁定表:

BEGIN TRANSACTION
DECLARE @ID AS NVARCHAR(10)
SET @ID =   (
                SELECT TOP 1 MyNo
                FROM Employee WITH (TABLOCKX, HOLDLOCK)
                WHERE (
                            (TypeID = @TypeID) AND
                            (Year = @Year)
                      )
                ORDER BY ID DESC
            )

SET @ID = ISNULL(@ID,0) + 1


INSERT INTO Employee (name,lname,MyNo) VALUES (@name,@lname,@MyNo)
COMMIT TRANSACTION

您可以在此处找到有关 TABLOCK 和 TABLOCKX 的更多信息: https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table

根据讨论,在这种情况下使用的最佳锁是:

(UPDLOCK,HOLDLOCK)

【讨论】:

  • 我认为值得注意的是,这似乎是一个应该由身份列作为主键的一部分来解决的问题。
  • 谢谢大家。但这是一个示例代码,而不是实际代码。实际代码是 varcharchar(10) 因为 no 类似于这个 no-year 示例 123-2017 而 123 是我生成它的增量 no,它不依赖于主键。
  • 亲爱的 JBdev,我只需要添加 BEGIN TRANSACTION 和 COMMIT TRANSACTION 吗?这会做表锁吗??
  • 不,实际上你需要一个Pk(身份)
  • 您是要锁定整个表还是只确保不生成重复项?
【解决方案2】:

如果您不能使用标识列或表锁,另一种选择是使用sp_getapplock

这种机制的优点是这种锁可以用于不应同时运行的多个存储过程或跨多个表的操作。如果锁不可用,它还允许处理超时和其他类型的行为。

您在使用此功能时必须小心,并确保正确获取和释放锁,否则您将产生比您解决的问题更多的问题。

【讨论】:

    猜你喜欢
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    相关资源
    最近更新 更多