SQL Server Express 和 SQL Server 2005 上的事务隔离和读取多个表

ath*_*ren 5 sql sql-server sql-server-2005 sql-server-2005-express

我有一个数据库,其中有一个主表(我们称之为所有者)和几个包含资产的子表(如汽车、书籍等)。

例如:

  • Owner有列:owner_id, name
  • Cars有列:owner_id (foreign key), brand
  • Books有列:owner_id (foreign key), title, author

我的程序应该使用各种第三方图书馆来计算统计数据,例如有多少宝马车主还拥有一本哈利波特书籍。我想同时读取所有表中的所有行,然后用非sql代码进行分析。

我想使用单独的语句读取所有表Select * From X。我无法使用一个大连接,因为它会返回太多行((所有者 * 汽车 * 书籍)而不是(所有者 + 汽车 + 书籍))。联合也不会削减它,因为表包含不同类型的不同列。

我已经设定

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
Run Code Online (Sandbox Code Playgroud)

但我还是有一些问题。

如果我通过运行两个线程来对数据库施加压力,一个随机插入或删除,另一个读取,有时会得到不一致的结果,例如在读取和读取表Cars之间已被删除。OwnersCars

我有几个问题:

  1. 从多个表逐一读取时防止修改的正确方法是什么?在读取所有表之前,不得修改任何表。

    我正在使用 SQL Server 2005(网络上)和 SQL Server 2005 Express(本地)。我可以同时显式地获取多个表的锁吗?

  2. 如果我针对本地 SQL Server Express 数据库运行,则无论我做什么都无法使其工作。如果我针对联网的 SQL Server 2005 数据库运行,我可以让它工作(需要付出一些努力)。SQL Server Express 是否支持事务隔离级别 SERIALIZABLE?我相信应该如此。差异可能是由于网络连接速度慢造成的,但我不知道。

    在我的本地数据库上,我无法阻止读取之间的修改。也就是说,一个线程随机删除一个随机所有者(首先是汽车,然后是书籍,然后是所有者)或插入一个新所有者(插入所有者,插入 2 辆车,插入 2 本书)。另一个线程正在阅读使用:

    Begin Tran
    Select owner_id From Owner
    Select owner_id, brand From Cars
    Select owner_id, title, author From Books
    Commit Tran
    
    Run Code Online (Sandbox Code Playgroud)

    无论我做什么,有时我都会遇到拥有零辆汽车或零本书的业主。这种情况永远不应该发生,因为所有插入和删除都在单个事务中。我似乎快递服务器不会同时锁定所有者、汽车和书籍语句。

    在联网的 SQL Server 2005 上,它工作正常,但这可能是因为连接速度较慢,因此同时执行的可能性较低。

  3. 在我的本地数据库上,我使用所有表中的虚拟来启动每个事务,Select以防止死锁。我不明白为什么这可以防止死锁,但不能防止表的修改。这在联网的 SQL Server 2005 上不是必需的。

目前,我无法判断我是否误解了事务隔离,或者这是否是 SQL Server Express 和 SQL Server 2005 之间差异的问题。任何帮助或见解将不胜感激。

gbn*_*gbn 3

您选择一次性加载所有数据意味着很少的选择:

  • 使用sp_getapplock通过相关代码来序列化访问
  • 在事务中的读取上使用 TABLOCKX、HOLDLOCK

您遇到问题是因为SET TRANSACTION ISOLATION LEVEL SERIALIZABLE只影响锁的隔离:您需要控制持续时间( HOLDLOCK) 和粒度+模式( TABLOCKX)