如何在SQL Server 2005/2008存储过程中实现Singleton模式?
我们希望存储过程将表中的下一个值返回给调用者,然后更新该值,以便下一个调用者获得不同的值...
但是会有许多来电者的时间!
AND 我们不希望阻止/超时问题
PS。也许单身不是答案......如果没有,你怎么能处理这个?
答案 0 :(得分:1)
根据定义,SINGLETON是一种锁定模式。
谈到数据库时,有很多数据库专业人员在提到“锁定”这个词时会感到害怕,但锁本身不是问题,它们是关系数据库的基本机制。
您必须了解锁的工作原理,存在何种锁,并尊重它们。 始终使用短事务,尽可能锁定最小行,使用集合而不是单个行。 当锁定很大,当它们持续时间过长时,锁定会成为一个问题,当然,当你构建一个DEADLOCK时。
所以,黄金法则,当您必须将数据更改为事务时,首先放置一个独占锁(UPDATE),而不是共享锁(SELECT),这意味着有时您必须开始执行假LOCK,如: / p>
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