backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized.

2023-04-12编程技术99724

昨天在检查YourSQLDba备份时,发现有台数据库做备份时出现了下面错误信息,如下所示:

<Exec>

  <ctx>yMaint.ShrinkLog</ctx>

  <inf>Log Shrink</inf>

  <Sql>

--  ========================================================================

-- Shrink of log file E:\SQL_LOG\xxxx_log.ldf

USE [xxxx]

DBCC SHRINKFILE (N'xxx_Log',      19043) with no_infomsgs           

--  ========================================================================

   </Sql>

  <err>Error 3023, Severity 16, level 2 : Backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized. Reissue the statement after the current backup or file manipulation operation is completed.

</err>

</Exec>

关于这个错误,是因为调整了作业的YourSQLDba_LogBackups的Schedule,导致YourSQLDba_FullBackups_And_Maintenance在运行时,事务日志备份已经开始了(这个数据库的事务日志由于索引重建、重组,会变得比较巨大),此时YourSQLDba_FullBackups_And_Maintenance作业执行收缩事务日志,就出现了这个错误。下面我们根据官方文档SQL Server generates a 3023 message when backup and file operations are tried at the same time来验证,测试一下这个错误出现的各类场景:

1: 当数据库正在做备份时,不允许修改恢复模式(Recovery Model)。

  There are limited recovery model changes allowed while backups are occurring.

 

会话1:执行备份数据库TEST

BACKUP DATABASE [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_20160705.bak' WITH NOFORMAT, NOINIT,  

       NAME = N'TEST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10;

GO

 

会话2:修改数据库的恢复模式。

USE [master]

GO

ALTER DATABASE [TEST] SET RECOVERY SIMPLE WITH NO_WAIT

GO

如上所示,在备份数据库TEST时,如果我们去修改数据库TEST的恢复模式,就会报这个错误,这是不允许的。

 

 

2:当数据库正在备份时,添加或删除文件是不允许的

You cannot add or drop files to a database while a backup is occurring.

测试验证如下

1:会话窗口1执行备份数据库TEST

BACKUP DATABASE [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_20160705.bak' WITH NOFORMAT, NOINIT,  

       NAME = N'TEST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10;

GO

 

2:会话窗口2执行增加日志文件时就会报错

USE [master]

GO

ALTER DATABASE [TEST] ADD FILE ( NAME = N'QCMDB_Data1', 

        FILENAME = N'D:\tmp\QCMDB_Data1.ndf' , SIZE = 5120KB , 

        MAXSIZE = 10485760KB , FILEGROWTH = 20480KB ) TO FILEGROUP [PRIMARY]

GO

-----------------------------------------------------------------------

Msg 3023, Level 16, State 2, Line 3

Backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized. Reissue the statement after the current backup or file manipulation operation is completed.

 

3:同一时刻只能允许一个事务日志备份(log backup),(当数据库正在做全备时,事务日志备份是允许的)

Only one log backup can happen at a time (a log backup is allowed when a full database backup is occurring).

关于这一点,同一时刻肯定只能允许一个事务日志备份,理论上不能出现两个并行的事务日志备份,这也是我纠结的地方,关于这段英文“Only one log backup can happen at a time (a log backup is allowed when a full database backup is occurring”, 是否两个事务日志备份是就会出现上述错误呢?

1:会话ID为64的窗口执行下面事务日志备份脚本

SELECT @@SPID;

BACKUP LOG [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_20160705_1430_1.trn' 

    WITH NOFORMAT, NOINIT, 

NAME = N'TEST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10

GO

 

2:会话ID为66的窗口执行下面事务日志备份脚本

SELECT @@SPID;

BACKUP LOG [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_20160705_1430_2.trn' 

    WITH NOFORMAT, NOINIT, 

NAME = N'TEST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10

GO

3:  在同时执行上面两个脚本前,最好先生成大量事务日志(我用重建TEST库里面几个大表的索引,生成了大量事务日志),然后同时执行上面两个窗口脚本(注意,由于需要人手工点击执行脚本,所以还是有点时间差),在第三个窗口查看会话信息

SELECT   [Spid] = er.session_id 

        ,[ecid] 

        ,[Database] = DB_NAME(sp.dbid) 

        ,[Start_Time]

        ,[SessionRunTime]    = datediff(SECOND, start_time,getdate())    

        ,[SqlRunTime]=     RIGHT(convert(varchar, 

                                 dateadd(ms, datediff(ms, sp.last_batch, getdate()), '1900-01-01'), 

                            121), 12)  

        ,[HostName]  

        ,[Users]=COALESCE(sp.LOGINAME, sp.nt_username)

        ,[Status] = er.status 

        ,[WaitType] = er.wait_type 

        ,[Waitime] = er.wait_time/1000   

        ,[Individual Query] = SUBSTRING(qt.text, er.statement_start_offset / 2,

                                       ( CASE WHEN er.statement_end_offset = -1

                                              THEN LEN(CONVERT(NVARCHAR(MAX), qt.text))

                                                   * 2

                                              ELSE er.statement_end_offset

                                         END - er.statement_start_offset ) / 2) 

        ,[Parent Query] = qt.text 

        ,[PROGRAM_NAME] = program_name 

FROM    sys.dm_exec_requests er

        INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid

        CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS qt

WHERE   session_Id >= 51;

如上所示,会话64在执行事务日志备份备份时,会话66被阻塞,他在等待更新锁(LCK_M_U),至于为什么有更新更新锁,使用SQL Profile跟踪看到下面信息,你也许就明白了。

所以我基本上很难构造两个并发的事务日志备份,我尝试使用两个作业在同一时刻运行事务日志备份,也无法实现并发的事务日志备份,真怀疑能否实现这样的场景,所以在这种场景下,我并不能重现这个错误信息。当然如果你取消第二个事务日志备份也会出现这个错误信息(此处实验没有截图,请见第五种情形),所以,个人理解应该是对英文文档理解的一些偏差。

4:当数据库正在备份时,不能收缩数据库文件。当然这里的备份包括完整备份和事务日志备份。

You cannot shrink files while database backups are happening.

会话1: 在数据库TEST上执行事务日志备份(备份前,为了实验效果,最好生成大量事务日志)

BACKUP LOG [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_20160705_1430_1.trn' 

    WITH NOFORMAT, NOINIT, 

NAME = N'TEST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10

GO

 

会话2:执行下面收缩TEST事务日志的SQL

USE TEST;

GO

DBCC SHRINKFILE(2,10);

备份数据库的时候,收缩数据库文件倒是能测试通过,不知道是否与我的测试案例有关系,也没有太多精力去研究、改造测试案例。有兴趣的可以研究一下。

5:同一时刻,只能做一个数据库备份操作(当数据库完整备份时,差异、增量备份不能同时出现)

Only one data backup can occur at a time (when a full database backup occurs, differential or incremental backups cannot occur at the same time).

1:会话66执行下面完整备份脚本

BACKUP DATABASE [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_20160705.bak' WITH NOFORMAT, NOINIT,  

 

       NAME = N'TEST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10;

 

GO

 

2:会话65执行下面差异备份脚本

BACKUP DATABASE [TEST] TO  DISK = N'D:\DB_BACKUP\TEST_DIFF_20160705_01.bak' 

    WITH  DIFFERENTIAL , NOFORMAT, NOINIT,  NAME = N'TEST-Full Database Backup',

     SKIP, NOREWIND, NOUNLOAD,  STATS = 10

GO

3:会话窗口3执行下面脚本,检查SQL之间的阻塞

 

 

  SELECT wt.blocking_session_id                    AS BlockingSessesionId

        ,sp.program_name                           AS Blocking_ProgramName

        ,COALESCE(sp.LOGINAME, sp.nt_username)     AS Blocking_HostName    

        ,ec1.client_net_address                    AS ClientIpAddress

        ,db.name                                   AS DatabaseName        

        ,wt.wait_type                              AS WaitType                    

        ,ec1.connect_time                          AS BlockingStartTime

        ,wt.WAIT_DURATION_MS/1000                  AS WaitDuration

        ,ec1.session_id                            AS BlockedSessionId

        ,h1.TEXT                                   AS BlockedSQLText

        ,h2.TEXT                                   AS BlockingSQLText

  FROM sys.dm_tran_locks  AS tl WITH(NOLOCK)

  INNER JOIN sys.databases AS db  WITH(NOLOCK)

    ON db.database_id = tl.resource_database_id

  INNER JOIN sys.dm_os_waiting_tasks AS wt  WITH(NOLOCK)

    ON tl.lock_owner_address = wt.resource_address

  INNER JOIN sys.dm_exec_connections  ec1 WITH(NOLOCK)

    ON ec1.session_id = tl.request_session_id

  INNER JOIN sys.dm_exec_connections  ec2 WITH(NOLOCK)

    ON ec2.session_id = wt.blocking_session_id

  LEFT OUTER JOIN master.dbo.sysprocesses AS sp WITH(NOLOCK)

    ON SP.spid = wt.blocking_session_id

  CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 

  CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2 

检查发现会话66(执行完整备份的会话)阻塞了会话65(差异备份的会话),但是如果我取消会话65,如下所示,就会发现出“backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized. Reissue the statement after the current backup or file manipulation operation is completed.”错误,当然,如果你不取消,不会出现这个错误,会话会一直阻塞,直到完整备份完成,然后继续执行差异备份。这个跟场景3基本上是一样的。

 

参考资料:

https://support.microsoft.com/en-us/kb/2979636

backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized.的相关教程结束。

本文地址:https://www.ufcn.cn/tutorials/2453233.html

如非特殊说明,本站内容均来自于网友自主分享,概不代表本站观点,如有任何问题我们都将在收到反馈后的第一时间进行处理!