根据定义,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