【问题标题】:How long should SET READ_COMMITTED_SNAPSHOT ON take?SET READ_COMMITTED_SNAPSHOT ON 需要多长时间?
【发布时间】:2010-09-18 22:35:06
【问题描述】:

运行需要多长时间

ALTER DATABASE [MySite] SET READ_COMMITTED_SNAPSHOT ON

我刚刚运行了它,花了 10 分钟。

如何查看是否应用?

【问题讨论】:

  • 哎呀。一直没有启用!! (说真的!)这解释了死锁。请参阅下面的答案以获取完整的发现和更好的运行脚本
  • 动作本身几乎立即完成。它不会返回的原因是因为它正在等待其他用户退出数据库。这不像是忙于思考、搅动、消耗资源;它正在等待每个人离开房间,所以它改变了拨动开关。
  • 如果您有打开的连接并且花费的时间太长,您可以强制所有打开的连接回滚并应用更改。小心潜在的影响:ALTER DATABASE yourdb SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE

标签: sql-server isolation-level read-committed-snapshot


【解决方案1】:

您可以使用 sys.databases 视图检查 READ_COMMITTED_SNAPSHOT 设置的状态。检查 is_read_committed_snapshot_on 列的值。已经asked and answered

至于持续时间,Books Online 声明在发生这种情况时不能与数据库建立任何其他连接,但它不需要单用户模式。因此,您可能会被其他活动连接阻止。运行 sp_who(或 sp_who2)查看还有什么连接到该数据库。

【讨论】:

  • 谢谢。到目前为止,它花了 40 分钟,显示为 0。它是一个 740mb 的数据库。手指交叉我没有打破它
  • 尝试针对该数据库打开另一个查询窗口。如果可以,那么我希望您的语句尚未开始运行。
  • 是的。在大多数数据库上应该只需要几秒钟。如果它需要更长的时间,它会在另一个(甚至是非活动的)连接后面等待终止,然后才能进行更改。因此,您可能需要查找并 KILL 当前连接的任何 spid(在评估它们正在做什么之后)。那么它应该很快。
  • 如果有其他打开的连接,我建议使用 NO_WAIT 选项立即失败。例如。 'ALTER DATABASE 通用 SET READ_COMMITTED_SNAPSHOT ON WITH NO_WAIT'
  • 如果您无法找到并杀死其他连接的 SPID(或者只是不关心),您可以随时重新启动 SQL Server 实例。
【解决方案2】:

试试这个:

ALTER DATABASE generic SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE

【讨论】:

  • 那么“WITH ROLLBACK IMMEDIATE”有什么用呢?这是否意味着它会在查询失败时自动回滚?
  • 否,“WITH ROLLBACK IMMEDIATE”意味着它将在启动 ALTER DATABASE 语句之前立即回滚任何打开的事务。我建议不要这样做,除非您已经检查了哪些事务是打开的以及它们是否可以安全回滚。
  • 太棒了,还报告关闭连接的进度。你救了我们的培根!
【解决方案3】:

好的(我是最初的提问者)所以事实证明我一直没有启用该死的东西。

这里是 ultimate code 运行以启用快照模式并确保它已启用。

SELECT is_read_committed_snapshot_on, snapshot_isolation_state_desc,snapshot_isolation_state FROM sys.databases WHERE name='shipperdb'

ALTER DATABASE shipperdb SET allow_snapshot_isolation ON
ALTER DATABASE shipperdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE shipperdb SET read_committed_snapshot ON
ALTER DATABASE shipperdb SET MULTI_USER

SELECT is_read_committed_snapshot_on, snapshot_isolation_state_desc,snapshot_isolation_state FROM sys.databases WHERE name='shipperdb'

即使在连接处于活动状态时也能正常工作(大概你可以接受它们被踢出)。

您可以看到之前和之后的状态,这应该几乎立即运行。


重要提示:

上面的选项 READ_COMMITTED_SNAPSHOT 对应于 .NET 中的 IsolationLevel.ReadCommitted
上面的选项 ALLOW_SNAPSHOT_ISOLATION 对应 .NET 中的 IsolationLevel.Snapshot

Great article about different versioning


.NET 提示:

看起来Isolationlevel.ReadCommitted 在代码中是允许的,即使数据库未启用也是如此。不会引发任何警告。因此,请帮自己一个忙,并确保它已打开,然后再假设它像我一样使用了 3 年!!!

如果您使用 C#,您可能需要 ReadCommitted IsolationLevel 而不是 Snapshot - 除非您在此事务中执行写入操作。

READ COMMITTED SNAPSHOT 进行乐观读取和悲观写入。相比之下,SNAPSHOT 进行乐观读取和乐观写入。 (from here)

bool snapshotEnabled = true;

using (var t = new TransactionScope(TransactionScopeOption.Required,
               new TransactionOptions
{
     IsolationLevel = IsolationLevel.ReadCommitted
}))
{
     using (var shipDB = new ShipperDBDataContext())
     {

     }
}

此外,您可能会收到有关“无法促进”交易的错误。在Introducing System.Transactions in the .NET Framework 2.0 中搜索“促销”。

除非您正在做一些特殊的事情,比如连接到外部数据库(或第二个数据库),否则像创建新 DataContext 这样简单的事情可能会导致这种情况。我有一个缓存,它在初始化时“启动”它自己的数据上下文,这试图将事务升级到一个完整的分布式事务。

解决方案很简单:

        using (var tran = new TransactionScope(TransactionScopeOption.Suppress))
        {
            using (var shipDB = new ShipperDBDataContext())
            { 
                 // initialize cache
            }
        }

另见Deadlocked article by @CodingHorror

【讨论】:

  • 我想提一下,因为我不确定:您可以独立于ALLOW_SNAPSHOT_ISOLATION 打开READ_COMMITTED_SNAPSHOT。您可以将ALLOW_SNAPSHOT_ISOLATION 关闭 并从READ_COMMITTED_SNAPSHOT 打开 中受益。测试:Microsoft SQL Server 2012 - 11.0.2100.60
  • 这个选项改变了 READ COMMITTED 的实现方式。关闭该选项后,SQL Server 将使用锁来控制访问。这就是为什么您的 .NET 代码没有生成警告的原因 - 您仍然得到该行为,只是以不同的(并且更有可能死锁)方式完成。
  • 这并没有回答原始问题,尽管由 OP 编写。它实现了一个替代方案。
【解决方案4】:

试试这个代码:

if(charindex('Microsoft SQL Server 2005',@@version) > 0)
begin
    declare @sql varchar(8000)
    select @sql = '
    ALTER DATABASE ' + DB_NAME() + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE ;
    ALTER DATABASE ' + DB_NAME() + ' SET READ_COMMITTED_SNAPSHOT ON;
    ALTER DATABASE ' + DB_NAME() + ' SET MULTI_USER;'

    Exec(@sql)
end

【讨论】:

  • 您应该使用 quotename() 包装您的 db_name() 调用,以说明数据库名称中可能需要转义的任何字符(如空格)。
  • 您还需要'SET allow_snapshot_isolation ON' 对吗? (见我的回答)
  • mssql 文档声称您确实需要设置允许快照隔离。但我真的很高兴在 SQL 服务器的喧嚣中找到这个可行的答案。
【解决方案5】:

我试过命令:

ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON
GO

针对一个开发盒,但它花了 10 多分钟,所以我杀了它。

然后我发现了这个:

https://willwarren.com/2015/10/12/sql-server-read-committed-snapshot/

并使用了他的代码块(运行大约需要 1:26):

USE master
GO

/** 
 * Cut off live connections
 * This will roll back any open transactions after 30 seconds and
 * restricts access to the DB to logins with sysadmin, dbcreator or
 * db_owner roles
 */
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK AFTER 30 SECONDS
GO

-- Enable RCSI for MyDB
ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON
GO

-- Allow connections to be established once again
ALTER DATABASE MyDB SET MULTI_USER
GO

-- Check the status afterwards to make sure it worked
SELECT is_read_committed_snapshot_on
FROM sys.databases
WHERE [name] = 'MyDB '

【讨论】:

    【解决方案6】:

    在更改当前数据库之前尝试使用主数据库。

    USE Master
    GO
    
    ALTER DATABASE [YourDatabase] SET READ_COMMITTED_SNAPSHOT ON
    GO
    

    【讨论】:

      【解决方案7】:

      当我将数据库更改为单用户时,我没有花一秒钟时间

      【讨论】:

        【解决方案8】:

        您需要做的就是: ALTER DATABASE xyz SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;

        无需将数据库置于单用户模式。 不过,您将回滚未提交的事务。

        【讨论】:

          【解决方案9】:

          尝试关闭其他 SQL 服务,以便只有 SQL 服务器服务正在运行。

          我的运行了 5 分钟,然后我取消了它,因为很明显没有发生任何事情。它是一个全新的服务器,因此没有其他用户连接。我关闭了 SQL Reporting Services,然后再次运行它。不到一秒钟就完成了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-06-20
            • 2011-12-26
            • 2015-10-05
            • 2012-06-30
            • 1970-01-01
            • 2011-07-18
            • 2011-03-09
            • 2014-12-15
            相关资源
            最近更新 更多