gpt4 book ai didi

sql - Sql事务的并发处理

转载 作者:行者123 更新时间:2023-12-03 22:25:54 25 4
gpt4 key购买 nike

假设我要使用ASP.NET和SQL Server 2005启动一个项目。我必须设计此应用程序的并发要求。我打算在每个表中添加一个TimeStamp列。更新表时,我将检查“时间戳”列是否与所选列相同。

这种方法足够了吗?还是在任何情况下这种方法都有缺点?

请指教。

谢谢

里约

最佳答案

首先,我认为您在问题中描述的方式是将MS SQL作为数据库的ASP.NET应用程序的最佳方式。数据库中没有锁定。对于像网络客户端一样永久断开客户端的用户,它是完美的选择。

如何从一些答案中读取内容,在术语上存在误解。我们都表示使用Microsoft SQL Server 2008或更高版本来保存数据库。如果您在MS SQL Server 2008文档中打开主题“行版本(Transact-SQL)”,则会发现以下内容:

"timestamp is the synonym for the rowversion data type and is subject to the behavior of data type synonym." … "The timestamp syntax is deprecated. This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature."



因此, 时间戳数据类型是MS SQL的 行版本数据类型的同义词。它拥有每个数据库内部存在的64位计数器,可以看作 @@ DBTS 。修改数据库的一个表中的一行后,计数器将增加。

在阅读您的问题时,我将“TimeStamp”读为 rowversion data类型的列名称。我个人更喜欢名称RowUpdateTimeStamp。在AzManDB中(请参阅Microsoft授权管理器,其存储为DB)我可以看到这样的名称。有时还使用ChildUpdateTimeStamp来跟踪分层的RowUpdateTimeStamp结构(与触发器有关)。

我在上一个项目中实现了这种方法,并且感到非常高兴。通常,您执行以下操作:
  • 将ROWtTimeStamp列添加到数据库的每个表中,类型为 rowversion (在Microsoft SQL Management Studio中将显示为时间戳,相同)。
  • 您应该构造所有SQL SELECT查询以将结果发送到客户端,以便与主数据一起发送其他RowVersion值。如果您有一个带有JOINT的SELECT,则应该从
  • 之类的两个表中发送最大RowUpdateTimeStamp值的RowVersion

    SELECT s.Id AS Id
    ,s.Name AS SoftwareName
    ,m.Name AS ManufacturerName
    ,CASE WHEN s.RowUpdateTimeStamp > m.RowUpdateTimeStamp
    THEN s.RowUpdateTimeStamp
    ELSE m.RowUpdateTimeStamp
    END AS RowUpdateTimeStamp
    FROM dbo.Software AS s
    INNER JOIN dbo.Manufacturer AS m ON s.Manufacturer_Id=m.Id

    或像下面这样进行数据转换

    SELECT s.Id AS Id
    ,s.Name AS SoftwareName
    ,m.Name AS ManufacturerName
    ,CASE WHEN s.RowUpdateTimeStamp > m.RowUpdateTimeStamp
    THEN CAST(s.RowUpdateTimeStamp AS bigint)
    ELSE CAST(m.RowUpdateTimeStamp AS bigint)
    END AS RowUpdateTimeStamp
    FROM dbo.Software AS s
    INNER JOIN dbo.Manufacturer AS m ON s.Manufacturer_Id=m.Id

    将RowUpdateTimeStamp保留为 bigint ,它对应于C#的 ulong 数据类型。如果您从多个表中进行OUTER JOINT或JOINT,则将看到来自所有表的 MAX(RowUpdateTimeStamp)构造会更加复杂。由于MS SQL不支持MAX(a,b,c,d,e)之类的功能,因此相应的构造可能如下所示:

    (SELECT MAX(rv)
    FROM (SELECT table1.RowUpdateTimeStamp AS rv
    UNION ALL SELECT table2.RowUpdateTimeStamp
    UNION ALL SELECT table3.RowUpdateTimeStamp
    UNION ALL SELECT table4.RowUpdateTimeStamp
    UNION ALL SELECT table5.RowUpdateTimeStamp) AS maxrv) AS RowUpdateTimeStamp
  • 所有断开连接的客户端(Web客户端)不仅接收并保存数据行,而且还接收并保存数据行的RowVersion(类型 ulong )。
  • 在尝试从断开连接的客户端修改数据的过程中,客户端应将与原始数据相对应的RowVersion发送到服务器。 spSoftwareUpdate存储过程可能看起来像

  • CREATE PROCEDURE dbo.spSoftwareUpdate
    @Id int,
    @SoftwareName varchar(100),
    @originalRowUpdateTimeStamp bigint, -- used for optimistic concurrency mechanism
    @NewRowUpdateTimeStamp bigint OUTPUT
    AS
    BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    -- ExecuteNonQuery() returns -1, but it is not an error
    -- one should test @NewRowUpdateTimeStamp for DBNull
    SET NOCOUNT ON;

    UPDATE dbo.Software
    SET Name = @SoftwareName
    WHERE Id = @Id AND RowUpdateTimeStamp <= @originalRowUpdateTimeStamp

    SET @NewRowUpdateTimeStamp = (SELECT RowUpdateTimeStamp
    FROM dbo.Software
    WHERE (@@ROWCOUNT > 0) AND (Id = @Id));
    END
    dbo.spSoftwareDelete存储过程的代码看起来相同。如果不打开 NOCOUNT,则可以生成在许多情况下自动生成的 DBConcurrencyException 。 Visual Studio使您可以使用诸如 TableAdapterDataAdapter的“高级选项”中的“使用乐观并发性”复选框之类的乐观并发性。

    如果您仔细看 dbo.spSoftwareUpdate存储过程,就会发现,我在WHERE中使用 RowUpdateTimeStamp <= @originalRowUpdateTimeStamp而不是 RowUpdateTimeStamp = @originalRowUpdateTimeStamp。我这样做是因为,具有客户端的 @originalRowUpdateTimeStamp的值通常从多个表中构造为 MAX(RowUpdateTimeStamp)。因此可以是 RowUpdateTimeStamp < @originalRowUpdateTimeStamp。您应该使用严格相等的 = 并在此处重现与SELECT语句中使用的相同的复杂JOIN语句,或者像我一样使用 <= 构造并保持与以前完全相同的安全性。

    顺便说一句,可以基于RowUpdateTimeStamp为ETag构造非常好的值(value),它可以与数据一起以HTTP header 发送到客户端。使用ETag,您可以在客户端实现智能数据缓存。

    我无法在此处编写完整的代码,但是您可以在Internet上找到很多示例。我只想再重复一遍,我认为基于 rowversion的乐观并发使用是大多数ASP.NET方案的最佳方法。

    关于sql - Sql事务的并发处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2658443/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com