【问题标题】:Singleton pattern in a stored procedure存储过程中的单例模式
【发布时间】:2013-12-06 07:31:21
【问题描述】:

如何在 SQL Server 2005/2008 存储过程中实现单例模式?

我们希望存储过程将表中的下一个值返回给调用者,然后更新该值,以便下一个调用者获得不同的值...

但是会有时间来电者很多

并且我们不希望出现阻塞/超时问题

PS。也许单身不是答案......如果不是,你怎么能处理这个

【问题讨论】:

  • 不能用序列吗?
  • 如果我理解正确,您可以使用类似update T set ID += 1 output inserted.ID
  • 或者如果它是你想要的之前的值那么update T set ID += 1 output deleted.ID
  • @AlexanderTorstling ... 好主意,但抱歉,这是 SQL Server 2005 和 2008 环境,我相信 SEQUENCE 是 2012 年的功能
  • @SteveC:如果您需要类似序列的功能,请查看以下问题:stackoverflow.com/questions/282943/…

标签: sql sql-server sql-server-2008 sql-server-2005 singleton


【解决方案1】:

根据定义,SINGLETON 是一种锁定模式。

说到数据库,很多数据库专业人士一提到“锁”这个词就会害怕,但锁本身不是问题,它们是关系数据库的基本机制。

您必须了解锁的工作原理,存在什么样的锁,并尊重它们。 始终使用短事务,尽可能锁定最少行,使用集合而不是单个行。 当锁很大时,当它们持续时间过长时,当然当你构建一个死锁时,锁就会成为一个问题。

所以,黄金法则,当你必须将数据更改为事务时,首先放置一个独占锁(UPDATE),而不是共享锁(SELECT),这意味着有时你必须开始做一个假锁,如:

BEGIN TRAN
   UPDATE table
     set col1 = col1
   Where Key = @Key
   .......
COMMIT TRAN

在 SQL Server 2012 之前,当我需要序列号时,我通过两种方式完成:

创建一个 IDENTITY 列,因此插入后您可以使用内置函数 SCOPE_IDENTITY() 获取值,还有@@IDENTITY,但如果有人创建一个触发器插入另一个表一个身份列开始了噩梦。

CREATE TABLE [table]
(
   Id int IDENTITY(1,1) NOT NULL,
   col2 ....
   col3 ....
)

第二种选择是通常在父表或为其制作的表中添加一个序列列,加上一个过程(您可以使用客户端代码)来获取序列:

--IF YOU CREATE A SERIAL HERE YOU'LL SPENT SOME SPACE,
--BUT IT WILL KEEP YOUR BLOCKINGS VERY LOW
CREATE TABLE Parent
(
  Id,
  ChildSerial  int  not null,
  col2 ...
  col3 ...
    CONSTRAINT PK_Parent PRIMARY KEY (Id)
)
GO

--NAMED CONSTRAINT Auto names are random (avoid them)
ALTER TABLE Parent
  ADD CONSTRAINT Parent_DF_ChildSerial DEFAULT(0) FOR ChildSerial;
GO

CREATE TABLE Child
(
   Id int not null
   col2..
   colN..
     --PLUS PRIMARY KEY... INDEXES, etc.
)

CREATE PROC GetChildId
(
  @PatentId       int
  @ChildSerial    int output  --To use the proc from another proc
)
As
Begin

   BEGIN TRAN
      --YOU START WITH A LOCK, SO YOU'LL NEVER GET A DEADLOCK
      --NOR A FAKE SERIAL (Two clients with the same number)
      UPDATE Parent
        SET ChildSerial = ChildSerial + 1
      WHERE Id = @PatentId

      If @@error != 0
          Begin
          SELECT @ChildSerial = -1
          SELECT @ChildSerial
          ROLLBACK TRAN
          RETURN
      End

      SELECT @ChildSerial = ChildSerial
      FROM Parent
      WHERE Id = @PatentId

   COMMIT TRAN

   SELECT @ChildSerial   --To Use the proc easily from a program

End
Go

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多