清空数据库事务日志
In my previous article in this series Accelerated Database Recovery; Instant Rollback and Database Recovery, we talked about a potential DBA painkiller to resolve long waiting times for database recovery and rollback scenarios using Accelerated Database Recovery. In this article, we will look at one more painful challenge for DBAs, Long Running Transaction with Transaction log growth.
在本系列的上一篇文章中,“ 加速数据库恢复”; 即时回滚和数据库恢复 ,我们讨论了一个潜在的DBA止痛药,它可以使用Accelerated Database Recovery解决数据库恢复和回滚方案的长时间等待。 在本文中,我们将探讨DBA的另一个痛苦挑战,即具有事务日志增长的长期事务处理。
You might have faced a situation in which a long-running query is causing excessive log growth. Due to an active transaction, SQL Server is not able to truncate the logs even in simple recovery model. You have limited space on the drive where the log file is situated. Suppose you have very limited free space remaining, then the only option is to kill the process, but again it will require transaction log space. We cannot control the behaviour of the transaction log to avoid such excessive log growth during long running transactions. Wait, don’t give up yet … The solution is described in further sections of this article.
您可能已经遇到了这样的情况:长时间运行的查询导致日志过度增长。 由于事务处于活动状态,因此即使在简单的恢复模型中,SQL Server也无法截断日志。 日志文件所在的驱动器上的空间有限。 假设您剩余的可用空间非常有限,那么唯一的选择是终止进程,但同样需要事务日志空间。 我们无法控制事务日志的行为,以避免在长时间运行的事务期间出现过多的日志增长。 请稍等,不要放弃……解决方案将在本文的其他部分中进行介绍。
Before we move on, let us look at SQL Server transaction log behaviour in brief.
在继续之前,让我们简要地看一下SQL Server事务日志行为。
SQL Server database consists of the following files.
SQL Server数据库由以下文件组成。
A transaction log file is a circular file that consists of Virtual Log Files (VLF). SQL Server logs the transaction in the transaction log, and when it reaches to end of the file, it reaches to the beginning of the log.
事务日志文件是由虚拟日志文件(VLF)组成的循环文件。 SQL Server将事务记录在事务日志中,当到达文件末尾时,它将到达日志的开头。
SQL Server runs the process to mark the VLF inactive if the recovery process does not require them. In the simple recovery process, you can see the log truncation after the transaction is committed. In Full recovery model, it requires log backup to complete before log truncation. If we do not have sufficient free space in drive or transaction log does not have space to grow due to max size limitation, you get the error 9002 of severity 17.
如果恢复过程不需要VLF,则SQL Server运行该过程以将VLF标记为不活动。 在简单的恢复过程中,您可以在提交事务后看到日志截断。 在完全恢复模式中,需要在日志截断之前完成日志备份。 如果驱动器中没有足够的可用空间,或者由于最大大小限制,事务日志没有增长空间,则会收到严重性为17的错误9002。
You can query sys.databases to identify why log space cannot be used.
您可以查询sys.databases以确定为什么无法使用日志空间。
select distinct(log_reuse_wait_desc) from sys.databases
It can have the following values:
它可以具有以下值:
In the following image, you can see the basic overview of transaction log circular behaviour.
在下图中,您可以看到事务日志循环行为的基本概述。
Suppose we have a log running active transaction for a particular database, SQL Server cannot truncate the logs due to ACTIVE_TRANSACTION. You cannot truncate the logs in FULL or BULK-LOGGED and Simple recovery model.
假设我们有一个日志正在运行特定数据库的活动事务,则由于ACTIVE_TRANSACTION ,SQL Server无法截断日志。 您无法截断日志 完整或批量记录以及简单的恢复模型。
In the following screenshot, you have a transaction log file with five VLF
在以下屏幕截图中,您有一个包含五个VLF的事务日志文件
If the logs are truncated, you can see the transaction log structure as follows.
如果日志被截断,您可以看到事务日志结构,如下所示。
Let us view the log running transaction issue with transaction log in the following example.
在下面的示例中,让我们查看带有事务日志的日志运行事务问题。
In SQL Server 2019 CTP, you can use the following query to check the status of this feature. If you are using other than SQL Server 2019 you check to perform this initial demo however in a later section; you need to use SQL Server 2019 that you can download from this link.
在SQL Server 2019 CTP中,您可以使用以下查询来检查此功能的状态。 如果您使用的不是SQL Server 2019,则在后面的部分中检查执行此初始演示; 您需要使用SQL Server 2019,您可以从此链接下载。
select name,is_accelerated_database_recovery_on from sys.databases
where name='SQLShackDemo'
We need to restrict the maximum transaction log size to 2 GB for this demo. Run the following Alter Database command to do it. We can do it using SSMS database properties page as well.
对于此演示,我们需要将最大事务日志大小限制为2 GB。 运行以下“ 更改数据库”命令来执行此操作。 我们也可以使用SSMS数据库属性页面来做到这一点。
USE [master]
GO
ALTER DATABASE [SQLShackDemo] MODIFY FILE ( NAME = N'SQLShackDemo_log', MAXSIZE = 2097152KB )
GO
Put the database into the Simple Recovery Model. SQL Server should truncate the logs once a transaction is committed.
将数据库放入简单恢复模型。 提交事务后,SQL Server应截断日志。
Before running the transaction, let us view the transaction log size using DMV sys.dm_db_log_stats
在运行事务之前,让我们使用DMV sys.dm_db_log_stats查看事务日志大小。
select
db_NAME(database_id) dbname,
recovery_model,
current_vlf_size_mb,
total_vlf_count,
active_vlf_count,
active_log_size_mb,
log_truncation_holdup_reason,
log_since_last_checkpoint_mb
from
sys.dm_db_log_Stats(DB_ID('SQLSHACKDEMO'))
In the following screenshot, you can see that currently we have only 0.14 MB active log size. We do not any running process to hold log truncation.
在以下屏幕截图中,您可以看到当前我们只有0.14 MB的活动日志大小。 我们没有任何正在运行的进程来保存日志截断。
We want to capture the log growth during an active transaction therefore, create a SQL table to
我们要捕获活动事务期间的日志增长,因此,创建一个SQL表以
Insert output from the DMV query mentioned above using SQL agent job.
使用SQL代理作业插入上述DMV查询的输出。
create Table TLogGrowth
(
Logcapturetime time(0),
DBname varchar(20),
recovery_model varchar(20),
current_vlf_size_mb int,
total_vlf_count int,
active_vlf_count int,
active_log_size_mb int,
log_truncation_holdup_reason varchar(20),
log_since_last_checkpoint_mb int
)
Configure a SQL Agent job to run following query every 30 seconds. In SQL Server Agent right -click on Jobs and create new job.
配置SQL代理作业以每30秒运行以下查询。 在SQL Server代理中,右键单击“作业”并创建新作业。
In the Job step, paste the query to insert a record into TLogGrowth table
在“作业”步骤中,粘贴查询以将记录插入到TLogGrowth表中
Use SQLShackDemo
Go
insert into TLogGrowth
select
convert(varchar, getdate(), 8),
db_NAME(database_id) dbname,
recovery_model,
current_vlf_size_mb,
total_vlf_count,
active_vlf_count,
total_log_size_mb,
active_log_size_mb,
log_truncation_holdup_reason,
log_since_last_checkpoint_mb
from
sys.dm_db_log_Stats(DB_ID('SQLSHACKDEMO'))
Specify the job frequency to every 30 seconds.
将作业频率指定为每30秒一次。
Now, run the following query to start the transaction. Please make sure SQL Server Agent should be running to capture transaction log growth.
现在,运行以下查询以启动事务。 请确保SQL Server代理应运行以捕获事务日志增长。
Begin transaction
Declare @Id int
Set @Id = 1
While @Id <= 10000
Begin
Insert Into tblSQLShackDemo(value) values (newid())
update tblSQLShackDemo set value=newid()
Set @Id = @Id + 1
End
In the output, you can see that the transaction log for database is full due to Active Transaction. It inserted only 2949 rows due to a limited maximum transaction log size.
在输出中,您可以看到由于Active Transaction导致数据库的事务日志已满。 由于最大事务日志大小的限制,它仅插入了2949行 。
Let us check the record in the tblSQLShackDemo table for the log file growth. We can see here that the total log size is 20147 MB and active log size is 951 MB. SQL Server could not truncate the transaction log due to ACTIVE_TRANSACTION as shown in the log_tuncate_holdup_reason column of the following output.
让我们检查tblSQLShackDemo表中的记录以了解日志文件的增长。 我们可以在此处看到总日志大小为20147 MB,活动日志大小为951 MB。 SQL Server无法截断事务日志由于ACTIVE_TRANSACTION作为显示在下面的输出log_tuncate_holdup_reason列。
SQL Server could not complete this particular transaction. Imagine this situation in a production environment where the transaction log is full due to an active transaction. You might have sufficient free space available. However, it would continue to grow the log file. It is not right in case of any disaster as well. SQL Server will have to rollback a complete transaction that might result in huge undo time. It is again a potential panic situation for DBA. We cannot control this behaviour of SQL Server. We can only ask developers to write down the efficient code and commit transaction frequently.
SQL Server无法完成此特定事务。 想象一下在生产环境中由于活动事务而事务日志已满的情况。 您可能有足够的可用空间。 但是,它将继续增长日志文件。 如果发生任何灾难,也是不正确的。 SQL Server将必须回滚一个完整的事务,这可能会导致大量的撤消时间。 对于DBA来说,这再次是潜在的恐慌情况。 我们无法控制SQL Server的这种行为。 我们只能要求开发人员写下有效的代码并频繁提交事务。
Let us run this transaction in SQL Server 2019 with enabled Accelerated Database Recovery feature.
让我们在启用了加速数据库恢复功能SQL Server 2019中运行此事务。
In the following screenshot, you can see the Accelerated Database Recovery feature is enabled on SQLShackDemo_ADR.
在以下屏幕截图中,您可以看到SQLShackDemo_ADR上启用了“加速数据库恢复”功能。
We will execute a similar workload in this database as well. We need to create SQL table in SQLShackDemo_ADR database and point the SQL Server Agent job as well on this ADR enabled database.
我们还将在该数据库中执行类似的工作量。 我们需要在SQLShackDemo_ADR数据库中创建SQL表,并在此启用ADR的数据库上也指向SQL Server代理作业。
Execute the same workload on Accelerated Database Recovery database. We are successful this time. Query executed successfully and inserted 10,000 records into a tblSQLShackDemo table in approximately 13 minutes.
在加速数据库恢复数据库上执行相同的工作负载。 这次我们成功了。 查询成功执行,并在大约13分钟内将10,000条记录插入到tblSQLShackDemo表中。
It is interesting to know transaction log usage for this database having Accelerated Database Recovery.
知道此数据库具有加速数据库恢复的事务日志使用情况很有趣。
We have the following observation regarding the log size
关于日志大小,我们有以下观察
In the following chart, we can see the comparison on transaction log growth between Accelerated Database Recovery feature On and Off
在下面的图表中,我们可以看到“打开和关闭”数据库加速功能之间的事务日志增长的比较
Initially, a transaction log grows in the Accelerated Database Recovery enabled database. It remains constant after initial growth. It is because we are using Persistent Version Store in and secondary log stream to store all necessary log records that we can go back and truncate the portion of the log because SQL Server does not require these for recovery and rollback. It is the reason SQL Server quickly rollback any transaction for Accelerated Database Recovery enabled database.
最初,事务日志在启用了Accelerated Database Recovery的数据库中增长。 初始增长后保持不变。 这是因为我们在持久性版本存储中和辅助日志流中使用了所有必需的日志记录,因此我们可以返回并截断部分日志,因为SQL Server不需要这些来进行恢复和回滚。 这就是SQL Server快速回退已启用“加速数据库恢复”的数据库的任何事务的原因。
Suppose we have a long-running active transaction for SQL Server database. Typically, we cannot shrink the transaction log in this case.
假设我们有一个长期运行SQL Server数据库活动事务。 通常,在这种情况下,我们无法收缩事务日志。
If we have limited free space in the drive, we try to do it, but it does not work. In below screenshot, we can see that log file has free space inside it; however, if we try to shrink it does not work.
如果驱动器中的可用空间有限,我们会尝试这样做,但是它不起作用。 在下面的屏幕截图中,我们可以看到日志文件内部具有可用空间; 但是,如果我们尝试缩小,则不起作用。
The Log file continues to grow. We have a simple recovery model in this database. Once the query succeeded or fails then only, we can shrink the log.
日志文件继续增长。 我们在此数据库中有一个简单的恢复模型。 一旦查询成功或失败,我们只能缩小日志。
Let us perform the transaction log shrink in Accelerated Database Recovery enabled database. In the following screenshot, we have 24% free space in the log.
让我们在启用“加速数据库恢复”的数据库中执行事务日志收缩。 在以下屏幕截图中,日志中有24%的可用空间。
Shrink the log, and we can see it shrinked the transaction log. You may not notice much change in the log size as it is already consuming a small transaction log, but it is entirely possible to shrink the transaction log file.
缩小日志,我们可以看到它缩小了事务日志。 您可能没有注意到日志大小的太大变化,因为它已经消耗了很小的事务日志,但是完全有可能缩小事务日志文件。
Accelerated Database Recovery; Instant Rollback and Database Recovery |
Accelerated Database Recovery and Long Running Transactions with Transaction Log Growth |
加速数据库恢复; 即时回滚和数据库恢复 |
通过事务日志增长加快数据库恢复和长期运行的事务 |
翻译自: https://www.sqlshack.com/accelerated-database-recovery-and-long-running-transactions-with-transaction-log-growth/
清空数据库事务日志