我有一个表格,每当用户点击我网站上的选项时,新数据就会被填充。我通过Management Studio创建了这个表,我想澄清一下,我每次都不是通过存储过程创建这个表,也不是使用任何类型的内存临时表。
每当用户点击我网站上的某个选项时,系统会先删除此表中的旧记录,然后填写新记录。我很担心当许多用户从我的网站点击相同的选项时可能出现的并发问题。我不知道SQL Server将如何处理多个删除并插入此表。
我在某处读到SQL Server服务会自动处理此问题,并为每个会话使用单独的会话式副本。
是否需要在我的表格中添加SPID,否则会自动处理?我是否需要将隔离级别从Read Committed更改为Serializable?
答案 0 :(得分:1)
您要问的问题的一般答案是,您需要在表中包含某种会话标识符列,并将每个用户/会话中的值传递给所有存储过程和/或SQL在该表上运行的语句。
可选的是,您可以将隔离级别设置为Serializable,并让您的用户排队等待,直到他们面前的所有人都完成并让SQL Server处理它,但这几乎不是您想要的要做。
粗略地说,对于第一个选项,你最终会得到类似的东西:
YourTable
ID DataCol1 DataCol2 DataCol3 .... User/SessionID
因此,用户在您的网站上登录/启动会话。您可以使用他们的ID或为他们生成SessionID并将其传递给
StoredProc1ClearSession @UserSessionID
StoredProc2InsertNewData (AnyOtherParamsYouHave),@UserSessionID
StoredProc3RetrieveData (AnyOtherParamsYouHave),@UserSessionID
你明白了。
基本上只要用于触及表的每个SQL语句都作为WHERE子句或insert语句的一部分:
UserSessionID or @UserSessionID
那么你可能正在努力建立一个可以由你描述的同时由几个用户安全共享的表。
对于第二种选择,请 read this让你意识到自己正在做什么。 :)
然后输入这样的代码
CREATE PROC yourstoredproc
paramaterslisted
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
YOURCODE TOUCHING TEMPTABLE HERE
COMMIT TRANSACTION;
以防您没有阅读链接:
SERIALIZABLE 指定以下内容:
这会阻止其他事务更新或插入任何符合当前事务执行的任何语句的行。这意味着如果事务中的任何语句第二次执行,它们将读取同一组行。范围锁保持到事务完成。这是隔离级别中最具限制性的,因为它会锁定整个键范围并保持锁定直到事务完成。由于并发性较低,因此仅在必要时使用此选项。此选项与在事务中所有SELECT语句中的所有表上设置HOLDLOCK具有相同的效果。
答案 1 :(得分:1)
您提到的“每个会话的单独副本”听起来像快照隔离,默认情况下不启用。
虽然具体细节在某种程度上取决于您同时进行的其他事务,但一般情况下,只需将DELETE和INSERT命令包装在单个事务中即可。您不需要提高隔离级别。
BEGIN TRAN
DELETE ...
INSERT ...
COMMIT TRAN