M.S*_*baa 5 t-sql sql-server transactions
我正在远程 sql server 数据库上做一些工作,这需要一些时间,我需要阻止任何其他连接到它,这样就不会丢失数据我相信我应该使用单用户模式来执行此操作
我需要在完成工作后将其恢复到多用户模式,但是我与远程服务器的连接不可靠,很多时候会在完成之前断开连接,通常只是自动回滚并稍后再执行,问题是当我尝试在事务中执行它我收到此错误:
多语句事务中不允许使用 ALTER DATABASE 语句
我该如何表现
ALTER DATABASE dbName
SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Run Code Online (Sandbox Code Playgroud)
在事务中并确保在断开连接时它将回滚到多用户模式?
因此,如果我们的连接断开,我们会尝试安排数据库返回到多用户模式。这是一种可行的方法,但它和罪恶一样丑陋。
首先,我们进行适当的设置:
create database RevertTest
go
use master
go
create table RevertLock (L int not null)
go
declare @rc int
declare @job_id uniqueidentifier
exec @rc = msdb..sp_add_job @job_name='RevertSingleUser',
@description='Revert the RevertTest database to multi_user mode',
@delete_level=3,
@job_id = @job_id OUTPUT
if @rc != 0 goto Failed
exec @rc = msdb..sp_add_jobstep @job_id = @job_id,
@step_name = 'Wait to revert',
@command = '
WHILE EXISTS (SELECT * FROM RevertLock)
WAITFOR DELAY ''00:00:01''
ALTER DATABASE RevertTest set multi_user
DROP TABLE RevertLock'
if @rc != 0 goto Failed
declare @nowish datetime
declare @StartDate int
declare @StartTime int
set @nowish = DATEADD(minute,30,GETDATE())
select @StartDate = DATEPART(year,@nowish) * 10000 + DATEPART(month,@nowish) * 100 + DATEPART(day,@nowish),
@StartTime = DATEPART(hour,@nowish) * 10000 + DATEPART(minute,@nowish) * 100 + DATEPART(second,@nowish)
exec @rc = msdb..sp_add_jobschedule @job_id = @job_id,
@name='Failsafe',
@freq_type=1,
@active_start_date = @StartDate,
@active_start_time = @StartTime
if @rc != 0 goto Failed
exec @rc = msdb..sp_add_jobserver @job_id = @job_id
if @rc != 0 goto Failed
print 'Good to go!'
goto Fin
Failed:
print 'No good - couldn''t establish rollback plan'
Fin:
Run Code Online (Sandbox Code Playgroud)
基本上,我们创造了一份可以在我们身后打扫卫生的工作。我们安排工作在半小时内开始运行,但这只是为了保护我们免受小型比赛的影响。
现在,我们运行实际的脚本来完成我们希望它完成的工作:
use RevertTest
go
alter database RevertTest set single_user with rollback immediate
go
begin transaction
go
insert into master..RevertLock(L) values (1)
go
exec msdb..sp_start_job @job_name='RevertSingleUser'
go
WAITFOR DELAY '01:00:00'
Run Code Online (Sandbox Code Playgroud)
如果运行此脚本,您将能够观察到数据库已进入单用户模式 - 最后WAITFOR DELAY只是为了模拟我们“做工作” - 无论您想在数据库中做什么在单用户模式下。如果停止此查询运行并断开此查询窗口,在一秒钟内您应该会看到数据库已返回到multi_user模式。
要成功完成脚本,只需将最后一个任务(之前COMMIT)设置为从RevertLock表中删除即可。就像断开连接一样,恢复作业1将负责将数据库切换回multi_user,然后自行清理。
1这份工作实际上有点欺骗性。它实际上不会循环并检查 master 中的表 - 因为您的事务由于INSERT. 相反,它会耐心等待获取合适的锁,这仅在事务提交或回滚时发生。