【发布时间】:2014-12-22 08:25:22
【问题描述】:
我需要将一些数据存储到数据库中,如果它被读取一次,则将其标记为“已使用”。它应该可以在同时调用 20 多个线程时正常工作。
这个想法是一个线程只能获得它的唯一值,但两个线程不能获得相同的值。对值列表的访问是通过一些 int 键和线程应该使用该键获取任何值,但不是多个线程具有相同的值
我创建了一个具有下一个结构的表
.
所以添加的存储过程很简单
ALTER PROCEDURE [dbo].[StorageAdd]
@key int,
@value nvarchar(100)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
INSERT INTO Storage(k, value, isUsed) VALUES (@key, @value, 0)
SELECT 1 as 'result', '' as 'message'
END TRY
BEGIN CATCH
SELECT 0 as 'result', 'Operation failed. Message = ' + ERROR_MESSAGE() as 'message'
END CATCH
END
但是在它之后我应该执行 SELECT 和 UPDATE 的地方并不那么明显
CREATE PROCEDURE StorageGet
@key int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRAN
BEGIN TRY
-- create variable for value
DECLARE @value nvarchar(100)
-- get first value from database
SET @value = (SELECT TOP 1 Storage.value FROM Storage WHERE Storage.k = @key AND Storage.isUsed = 0)
IF(@value IS NULL OR @value = '')
BEGIN
ROLLBACK
SELECT 0 as 'result', 'No items found' as 'message', '' as 'value'
RETURN
END
UPDATE Storage SET Storage.isUsed = 1 WHERE Storage.k = @key AND Storage.value = @value
IF @@ERROR <> 0
BEGIN
-- in case of error roll back this transaction
ROLLBACK
-- return 0
SELECT 0 as 'result', 'Insert article ID failed. Error code = ' + CONVERT(varchar(5), @@ERROR) as 'message', '' as 'value'
RETURN
END
COMMIT TRAN
SELECT 1 as 'result', '' as 'message', @value as 'value'
END TRY
BEGIN CATCH
-- in case of error roll back this transaction
ROLLBACK
-- return 0
SELECT 0 as 'result', 'Operation failed. Message = ' + ERROR_MESSAGE() as 'error'
RETURN
END CATCH
END
GO
那么我的事务会是多线程安全的吗?
首先,我为在更新它使用的行之前和之后未使用的表选择最高值。可能的问题是,如果我同时运行 100 次执行,则 2 个线程可以同时进行选择并获得相同的值,之后两者都会更新这一行。
结果我将有 2 个线程具有相同的值且没有错误。
我的事务线程是否安全?我使用 MS SQL Server 2008 和 2012。
【问题讨论】:
标签: sql-server multithreading sql-server-2008 transactions sql-server-2012