SQL Server (2012) 非阻塞 DDL?

a_h*_*ame 5 concurrency ddl sql-server-2012

我对 SQL Server 不是很有经验,所以也许我遗漏了一些东西

我的情况如下:

  • 会话 1 在关闭自动提交的情况下运行 CREATE TABLE(或其他 CREATE 语句)并且未提交 CREATE。
  • 会话 2 运行一条sp_table语句,但只要会话 1 没有提交 DDL 就会挂起

发生这种情况的场景是开发人员在数据库上工作。他们中的一些人浏览表格,一些人做 DDL。如果一个用户忘记提交 DDL,所有其他想要列出表的会话都会被阻止。请注意,sp_tables例如由 SQL 客户端(通过 JDBC 驱动程序 API)发出,因此它不能更改。

我正在使用的数据库启用了 snapshot_isolation 并且隔离级别设置为已提交读(SET ALLOW_SNAPSHOT_ISOLATION ONSET READ_COMMITTED_SNAPSHOT ON

我的假设是这些设置应该使 SQL Server 在锁定并发会话方面表现得更好(例如 PostgreSQL 和 Oracle,其中 SELECT 永远不会被任何作者阻止) - 但显然情况并非如此。

那么,有没有什么方法可以使 SQL Server 对 DDL 的并发读/写情况更加友好?(除了仅在自动提交模式下提交 DDL)。

Mar*_*ith 6

不,没有办法配置 SQL Server 来做你想做的事。

下快照隔离呼叫sp_tables被阻塞,等待共享密钥锁定在系统基本表中的一个(sysschobjs)做了当SELECTsys.all_objects

BOL 中的Using Row Versioning-based Isolation Levels主题确实说:

SQL Server 不会保留多个版本的系统元数据。表和其他数据库对象(索引、视图、数据类型、存储过程和公共语言运行时函数)上的数据定义语言 (DDL) 语句会更改元数据。

然而,即使在TRANSACTION ISOLATION LEVEL READ UNCOMMITTED调用sp_tables结束时也会阻塞,虽然SELECT ... FROM sys.all_objects不再阻塞,但相同的查询引用HAS_PERMS_BY_NAMEWHERE子句中的函数。这似乎以CMetadataAccessor::CMetadataAcce更高的隔离级别启动系统事务 ( ) 并最终被阻塞,等待共享密钥sysschobjs再次锁定。