数据库隔离模型

时间:2012-11-16 06:20:47

标签: asp.net sql-server vb.net sql-server-2008 sql-server-2008-r2

我有一个带有“ID”列的数据库。每当有一个新的数据库条目时,我从数据库中获取最后一个ID,增加该值,然后在Insert语句中使用它。

编辑:我需要在多个Insert语句中使用该ID。我将从主表中获取此ID,并使用此ID将值插入相关表中。

    NextID = Select Max(ID) + 1 From Table

    INSERT INTO Table1(ID, Col1, Col2...) Values(NextId, Value1, Value2...)

    INSERT INTO Table2 (ID,col1,col2....) Values (NextID, Value1, Value2...)

我不知道这是否是一种好方法,因为我知道会出现并发问题。 当我的应用程序尝试读取NextID时,应用程序的另一个实例也可能尝试读取相同的值,因此可能会出现并发问题。

有没有正确的方法来处理这种情况?我的意思是有一些方法来设置数据库隔离级别。对于这种情况,这将是一个适当的隔离级别。

此外,如果有人建议我使用另一种方法来手动维护和增加数据库中的ID,我也会对此持开放态度。

如果此信息不足,请告诉我您的需求。

我正在使用ASP和Net与VB和MS Sql Server 2008.我不想使用SQL Server的内置“身份”。

3 个答案:

答案 0 :(得分:3)

获取下一个ID的唯一方法是实际插入行,并使用identity。其他一切都会失败。所以你必须从插入父表开始:

begin transaction;
insert into Table (col1, col2, col3) values (value1, value2, value3);
set @Id = scope_identity();
insert into Table1(ID, col1, col2) values (@Id, ...);
insert into Table3(ID, col1, col2) values (@Id, ...);
commit;

这是原子和并发安全的。

  

我不想使用SQL Server的内置“身份”。

TL;博士。你想要的东西很少,除非你能明确说明理由为什么。你可以正确地做到这一点,或者你可以花时间'忘记重新发明轮子。

答案 1 :(得分:1)

实际上,您有一批三个SQL语句 - 一个选择和两个插入。数据库引擎可以从它们之间的任何位置执行另一个语句,从而破坏您的数据一致性 - 其他一些会话可以获得与您相同的MAX()值并将其用于其他插入语句。防止数据库引擎执行此操作的唯一方法是使用事务。用BEGIN TRANSACTION ... COMMIT包装您的批次,你就完成了。

答案 2 :(得分:1)

你这样做的方式很好,你需要的是交易处理..

BEGIN TRANSACTION 

begin try
    NextID = Select Max(ID) + 1 From Table

    INSERT INTO Table1(ID, Col1, Col2...) Values(NextId, Value1, Value2...)

    INSERT INTO Table2 (ID,col1,col2....) Values (NextID, Value1, Value2...)

    COMMIT TRANSACTION 
end try

begin catch

    ROLLBACK TRANSACTION 
    --exception logging goes here

end catch