我对 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 ON
和SET READ_COMMITTED_SNAPSHOT ON
)
我的假设是这些设置应该使 SQL Server 在锁定并发会话方面表现得更好(例如 PostgreSQL 和 Oracle,其中 SELECT 永远不会被任何作者阻止) - 但显然情况并非如此。
那么,有什么方法可以让 SQL Server 对 DDL 的并发读/写情况更加友好?(除了仅在自动提交模式下提交 DDL)。
不,没有办法配置 SQL Server 来做你想做的事。
在快照隔离下,
sp_tables
当sysschobjs
执行SELECT
fromsys.all_objects
BOL 中的Using Row Versioning-based Isolation Levels主题确实说:
然而,即使在最终阻塞
TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
的调用下,当直接前进不再被阻塞时,相同的查询也会引用子句中的函数。这似乎以更高的隔离级别启动系统事务 ( ) 并最终被阻塞,等待共享密钥再次锁定。sp_tables
SELECT ... FROM sys.all_objects
HAS_PERMS_BY_NAME
WHERE
CMetadataAccessor::CMetadataAcce
sysschobjs
一个想法:每 15 秒安排一次作业,以查找空闲的未提交 DDL 并终止会话并将它们回滚。