我想知道是否可以在 MS SQL Server 2005 或更高版本中创建一个非常快速且临时的表(基本上驻留在 RAM 中)以用于软件间通信?如果可能的话,所有正常的锁定功能是否也适用于此类表?我们有一个旧软件想要通过数据库接收消息,目前它只使用一个普通的表,尽管它确实不需要在重新启动时保留其状态。我们还想在该表上使用存储的 TSQL 过程。
主页
/
user-284402
The amateur programmer's questions
The amateur programmer
Asked:
2023-12-22 19:03:07 +0800 CST
我想让旧的后续查询在并行运行时免受数据竞争的影响。该查询使用特定条件检查表中是否存在一行,如果不存在该行,则会插入包含新数据的新行。旧查询粘贴如下:
BEGIN
DECLARE @txtPer VARCHAR(MAX) = @nro;
DECLARE @txtCmin VARCHAR(MAX) = @min;
DECLARE @txtCmax VARCHAR(MAX) = @max;
IF NOT EXISTS (SELECT 1 FROM SEND WHERE MSG LIKE (@txtPer + '%') AND STATE < 2 AND ID = 1)
BEGIN
----Time of check is not time of use
----Someone could possibly do another insert before this == data race
INSERT INTO SEND (SNDID, ID, MSGCODE, MSG, STATE, INFO, INFO_TEXT, CHANGEDATE, CREATEDATE)
SELECT MAX(SNDID)+10,1,1,(@txtPer + @txtCmin + ' ' + @txtCmax),0,0,' ',getdate(),getdate() FROM SEND
END
END
我想出了一个稍微干净一点的新版本,并使用独占表锁:
BEGIN TRANSACTION;
DECLARE @txtPer VARCHAR(MAX) = @nro;
DECLARE @txtCmin VARCHAR(MAX) = @min;
DECLARE @txtCmax VARCHAR(MAX) = @max;
DECLARE @IdMax INT
--Get MAX and simultaneously acquire lock for the table to prevent modifications during this transaction?
SELECT @IdMax=MAX(SNDID) FROM SEND WITH(TABLOCKX)
IF NOT EXISTS(SELECT 1 FROM SEND WHERE MSG LIKE (@txtPer + '%') AND STATE < 2 AND ID = 1)
BEGIN
INSERT INTO SEND (SNDID, ID, MSGCODE, MSG, STATE, INFO, INFO_TEXT, CHANGEDATE, CREATEDATE)
VALUES((@IdMax + 10),1,1,(@txtPer + @txtCmin + ' ' + @txtCmax),0,0,' ',getdate(),getdate())
END
COMMIT; --writes potential change and releases table lock?
我的理解是否正确,即在操作期间获取的表锁SELECT MAX()
(可能还有同一事务中的其他表锁)一直保留到整个事务完成该COMMIT
语句?DB 是旧的 MS SQL Server 2005。