Set read_committed_snapshot On for Databases in an Availability Group

本文介绍了一种在SQL Server中不使用KILL命令而通过移除用户权限来设置数据库为读已提交快照的方法,并提供了具体的步骤和SQL语句。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常为数据库开启read_committed_snapshot需要将数据库设置为单用户模式来关闭数据库上的连接,但是如果数据库在alwayson集群中时,无法运行set single_user,测试发现只要主节点上的数据库没有任何的连接(不需要关心副节点),就能运行set read_committed_snapshot on

那么我们可以通过kill把数据库上的所有连接断掉

use master
go

declare @execSql varchar(1000), @databaseName varchar(100)
-- Set the database name for which to kill the connections
set @databaseName = 'test'
set @execSql = ''
select @execSql = @execSql + 'kill ' +
CONVERT(char(10), spid) + ' '
from master.dbo.sysprocesses
where db_name(dbid) = @databaseName
AND DBID <> 0
AND spid <> @@spid
exec(@execSql)

为了防止程序自动连接,可以先将访问数据库的用户权限去除,在操作完成后,再将用户权限加回去。

我这里实际操作没有使用kill,而是通过去除用户权限,连接就直接断了

USE [test]
GO
DROP USER [test1]
GO

USE [master]
GO
ALTER DATABASE [test] SET READ_COMMITTED_SNAPSHOT ON WITH NO_WAIT
GO

USE [test]
GO
CREATE USER [test1] FOR LOGIN [test1]
GO
ALTER ROLE [db_datareader] ADD MEMBER [test1]
GO
ALTER ROLE [db_datawriter] ADD MEMBER [test1]
GO

 

转载于:https://www.cnblogs.com/mowl/p/9364177.html

<think>我们正在讨论SQLServer中的read_committed_snapshot选项。根据引用,这个选项与事务隔离级别有关,特别是当数据库使用READ COMMITTED隔离级别时,开启read_committed_snapshot可以改变其行为,避免读写阻塞,类似于Oracle的读一致性。引用[1]提到设置隔离级别为Readcommitted snapshot。引用[2]和[3]展示了如何查询当前数据库read_committed_snapshot状态。引用[4]解释了不同隔离级别的行为,包括readuncommitted允许脏读,而readcommitted snapshot则不会。引用[5]说明了在read committed隔离级别下开启snapshot选项时,update操作的旧数据会保存在tempdb中,其他连接可以看到update之前的旧数据(即非阻塞读)。用户问题:如何设置和使用SQLServer的read_committed_snapshot选项?回答步骤:1.解释read_committed_snapshot的作用:开启后,在READ COMMITTED隔离级别下,读操作不会阻塞写操作,写操作也不会阻塞读操作。它使用行版本控制,将修改前的数据版本存储在tempdb中,读操作读取的是修改前的版本(在事务开始时的版本)。2.设置条件:数据库必须处于单用户模式(因为设置选项需要独占访问)。3.设置步骤:先设置数据库为单用户模式,然后设置选项,再改回多用户模式。4.验证设置:通过查询系统视图确认设置是否生效。5.使用说明:设置后,所有使用默认READ COMMITTED隔离级别的事务将自动使用行版本控制,无需修改应用程序代码(但需注意,应用程序的行为会改变,因为不会出现读阻塞写或写阻塞读的情况)。注意:开启此选项会增加tempdb的负担,因为需要存储旧版本数据。根据引用[2]和[3],查询read_committed_snapshot状态的SQL语句为: ```sqlSELECT name, is_read_committed_snapshot_onFROM sys.databasesWHERE name= 'YourDatabaseName'; ```设置read_committed_snapshot的步骤(需要sysadmin权限):1.将数据库设置为单用户模式:```sqlALTERDATABASEYourDatabaseName SETSINGLE_USER WITHROLLBACK IMMEDIATE;```2.设置read_committed_snapshot选项为ON:```sqlALTERDATABASEYourDatabaseName SETREAD_COMMITTED_SNAPSHOT ON;```3.将数据库设置回多用户模式:```sqlALTERDATABASEYourDatabaseName SETMULTI_USER;```设置完成后,所有使用默认READ COMMITTED隔离级别的事务将使用行版本控制,而不是共享锁。注意:在设置过程中,第一步会立即回滚所有当前连接,因此需要在维护时段进行。另外,引用[4]和[5]提到,readcommittedsnapshot隔离级别与snapshot隔离级别不同。readcommitted snapshot只在语句级别提供行版本,而snapshot隔离级别在事务级别提供行版本(需要单独设置SNAPSHOT_ISOLATION)。因此,用户如果希望使用行版本来避免阻塞,但又不希望改变当前应用程序的隔离级别设置(即仍然使用READCOMMITTED),那么开启read_committed_snapshot是一个好的选择。相关问题:1.开启read_committed_snapshot对tempdb有什么影响?2.如何监控read_committed_snapshot开启后的性能?3. read_committed_snapshotsnapshot隔离级别有什么区别?</think>### SQL Server read_committed_snapshot 设置与使用指南 `read_committed_snapshot` 是 SQL Server 的关键数据库选项,它通过行版本控制机制实现非阻塞读操作。当开启时,在 `READ COMMITTED` 隔离级别下,读操作不会阻塞写操作,写操作也不会阻塞读操作,而是从 `tempdb` 中读取修改前的数据版本[^4][^5]。 #### 一、设置方法 1. **检查当前状态**(需 `VIEW DATABASE STATE` 权限): ```sql SELECT name, is_read_committed_snapshot_on FROM sys.databases WHERE name = 'YourDatabaseName'; -- 替换为实际数据库名 ``` 返回值 `1` 表示开启,`0` 表示关闭[^2][^3]。 2. **开启步骤**(需 `sysadmin` 权限): ```sql -- 1. 设置数据库为单用户模式(断开其他连接) ALTER DATABASE YourDatabaseName SET SINGLE_USER WITH ROLLBACK IMMEDIATE; -- 2. 启用 read_committed_snapshot ALTER DATABASE YourDatabaseName SET READ_COMMITTED_SNAPSHOT ON; -- 3. 恢复多用户模式 ALTER DATABASE YourDatabaseName SET MULTI_USER; ``` ⚠️ 操作需在维护窗口进行,因 `SET SINGLE_USER` 会中断现有连接[^1]。 #### 二、核心作用 1. **解决阻塞问题**: - 未开启时:读操作 (`SELECT`) 会加共享锁,阻塞写操作 (`UPDATE`)[^4] - 开启后:读操作读取 `tempdb` 中的行版本,写操作可立即执行 ```mermaid graph LR A[SELECT 查询] -->|未开启| B[阻塞 UPDATE] A -->|开启后| C[从 tempdb 读快照] D[UPDATE 操作] -->|开启后| E[写入新版本到 tempdb] ``` 2. **隔离级别行为变化**: - 默认 `READ COMMITTED` 隔离级别自动升级为行版本控制 - 事务中每条 `SELECT` 语句都读取语句开始时的最新已提交版本[^5] #### 三、使用注意事项 1. **资源开销**: - 增加 `tempdb` 负载(存储行版本) - 监控语句:`SELECT * FROM sys.dm_tran_version_store` - 建议单独配置 `tempdb` 存储[^5] 2. **应用兼容性**: ```sql -- 显式指定隔离级别(推荐) SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN TRAN SELECT * FROM Orders; COMMIT ``` - 需避免长时间事务:旧版本在 `tempdb` 中保留至事务结束 3. **与快照隔离区别**: | 特性 | `READ_COMMITTED_SNAPSHOT` | `SNAPSHOT_ISOLATION` | |---------------------|---------------------------|----------------------| | 版本读取时机 | 语句开始时 | 事务开始时 | | 更新冲突检测 | 无 | 有(引发更新失败) | | 设置选项 | `READ_COMMITTED_SNAPSHOT` | `ALLOW_SNAPSHOT_ISOLATION` | #### 四、验证配置效果 1. 测试读写阻塞: ```sql -- 会话1(更新数据) BEGIN TRAN UPDATE Products SET Price = 20 WHERE ProductID = 1 -- 会话2(查询应立刻返回旧值) SELECT Price FROM Products WHERE ProductID = 1 -- 不阻塞 ``` 2. 监控版本存储: ```sql SELECT DB_NAME(database_id), COUNT(*) AS VersionCount FROM sys.dm_tran_version_store GROUP BY database_id; ``` > **重要提示**:开启后需测试应用逻辑一致性,某些依赖阻塞行为的应用可能需要调整[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值