Files
sql-server-samples/samples/features/accelerated-database-recovery/basic_adr.ipynb
T
2019-11-02 17:06:18 -07:00

51 KiB

Accelerated Database Recovery - Fast rollback and log truncation

In this example you will see how fast rollback can now be with Accelerated Database Recovery. You will also see that a long active transaction does not affect the ability to truncate the transaction log.

Step 1: Setup the database

This demo uses the WideWorldImportersDW database. You can get the WideWorldImportersDW-Full.bak database backup file from https://github.com/Microsoft/sql-server-samples/releases/tag/wide-world-importers-v1.0.

The log file is enlarged to 4GB to avoid any autogrow.

Leave the database SIMPLE recovery to make it easier to analyze log truncation.

The database assumes a path for a standard SQL Server Windows installation.

Note: For Linux installations the default path to use is /var/opt/mssql

In [35]:
USE [master]
GO
IF EXISTS (SELECT [database_id] FROM sys.databases WHERE [name] = 'WideWorldImportersDW')
ALTER DATABASE [WideWorldImportersDW] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

DECLARE @datafilepath VARCHAR(8000) = CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS VARCHAR(4000)) + 'WideWorldImportersDW.mdf'
DECLARE @logfilepath VARCHAR(8000) = CAST(SERVERPROPERTY('InstanceDefaultLogPath') AS VARCHAR(4000)) + 'WideWorldImportersDW.ldf'
DECLARE @inmemfilepath VARCHAR(8000) = CAST(SERVERPROPERTY('InstanceDefaultLogPath') AS VARCHAR(4000)) + 'WideWorldImportersDW_InMemory_Data_1'
DECLARE @secondaryfilepath VARCHAR(8000) = CAST(SERVERPROPERTY('InstanceDefaultLogPath') AS VARCHAR(4000))+ 'WideWorldImportersDW_2.ndf'

-- Change @backupfile file path as needed
DECLARE @backupfile VARCHAR(8000) = 'E:\SampleDBs\WideWorldImportersDW-Full.bak'
RESTORE DATABASE WideWorldImportersDW
FROM DISK = @backupfile 
WITH MOVE 'WWI_Primary' TO @datafilepath,
    MOVE 'WWI_UserData' TO @secondaryfilepath,
    MOVE 'WWIDW_InMemory_Data_1' TO @inmemfilepath,
    MOVE 'WWI_Log' TO @logfilepath, NOUNLOAD, REPLACE, STATS = 10
GO

USE [master]
GO
ALTER DATABASE [WideWorldImportersDW] MODIFY FILE ( NAME = N'WWI_Log', SIZE = 4GB )
GO
Commands completed successfully.
Commands completed successfully.
10 percent processed.
Processed 1192 pages for database 'WideWorldImportersDW', file 'WWI_Primary' on file 1.
Processed 28184 pages for database 'WideWorldImportersDW', file 'WWI_UserData' on file 1.
Processed 26 pages for database 'WideWorldImportersDW', file 'WWI_Log' on file 1.
Processed 24 pages for database 'WideWorldImportersDW', file 'WWIDW_InMemory_Data_1' on file 1.
Converting database 'WideWorldImportersDW' from version 852 to the current version 904.
Database 'WideWorldImportersDW' running the upgrade step from version 852 to version 853.
Database 'WideWorldImportersDW' running the upgrade step from version 853 to version 854.
Database 'WideWorldImportersDW' running the upgrade step from version 854 to version 855.
Database 'WideWorldImportersDW' running the upgrade step from version 855 to version 856.
Database 'WideWorldImportersDW' running the upgrade step from version 856 to version 857.
Database 'WideWorldImportersDW' running the upgrade step from version 857 to version 858.
Database 'WideWorldImportersDW' running the upgrade step from version 858 to version 859.
Database 'WideWorldImportersDW' running the upgrade step from version 859 to version 860.
Database 'WideWorldImportersDW' running the upgrade step from version 860 to version 861.
Database 'WideWorldImportersDW' running the upgrade step from version 861 to version 862.
Database 'WideWorldImportersDW' running the upgrade step from version 862 to version 863.
Database 'WideWorldImportersDW' running the upgrade step from version 863 to version 864.
Database 'WideWorldImportersDW' running the upgrade step from version 864 to version 865.
Database 'WideWorldImportersDW' running the upgrade step from version 865 to version 866.
Database 'WideWorldImportersDW' running the upgrade step from version 866 to version 867.
Database 'WideWorldImportersDW' running the upgrade step from version 867 to version 868.
Database 'WideWorldImportersDW' running the upgrade step from version 868 to version 869.
Database 'WideWorldImportersDW' running the upgrade step from version 869 to version 875.
Database 'WideWorldImportersDW' running the upgrade step from version 875 to version 876.
Database 'WideWorldImportersDW' running the upgrade step from version 876 to version 877.
Database 'WideWorldImportersDW' running the upgrade step from version 877 to version 878.
Database 'WideWorldImportersDW' running the upgrade step from version 878 to version 879.
Database 'WideWorldImportersDW' running the upgrade step from version 879 to version 880.
Database 'WideWorldImportersDW' running the upgrade step from version 880 to version 881.
Database 'WideWorldImportersDW' running the upgrade step from version 881 to version 882.
Database 'WideWorldImportersDW' running the upgrade step from version 882 to version 883.
Database 'WideWorldImportersDW' running the upgrade step from version 883 to version 884.
Database 'WideWorldImportersDW' running the upgrade step from version 884 to version 885.
Database 'WideWorldImportersDW' running the upgrade step from version 885 to version 886.
Database 'WideWorldImportersDW' running the upgrade step from version 886 to version 887.
Database 'WideWorldImportersDW' running the upgrade step from version 887 to version 888.
Database 'WideWorldImportersDW' running the upgrade step from version 888 to version 889.
Database 'WideWorldImportersDW' running the upgrade step from version 889 to version 890.
Database 'WideWorldImportersDW' running the upgrade step from version 890 to version 891.
Database 'WideWorldImportersDW' running the upgrade step from version 891 to version 892.
Database 'WideWorldImportersDW' running the upgrade step from version 892 to version 893.
Database 'WideWorldImportersDW' running the upgrade step from version 893 to version 894.
Database 'WideWorldImportersDW' running the upgrade step from version 894 to version 895.
Database 'WideWorldImportersDW' running the upgrade step from version 895 to version 896.
Database 'WideWorldImportersDW' running the upgrade step from version 896 to version 897.
Database 'WideWorldImportersDW' running the upgrade step from version 897 to version 898.
Database 'WideWorldImportersDW' running the upgrade step from version 898 to version 899.
Database 'WideWorldImportersDW' running the upgrade step from version 899 to version 900.
Database 'WideWorldImportersDW' running the upgrade step from version 900 to version 901.
Database 'WideWorldImportersDW' running the upgrade step from version 901 to version 902.
Database 'WideWorldImportersDW' running the upgrade step from version 902 to version 903.
Database 'WideWorldImportersDW' running the upgrade step from version 903 to version 904.
100 percent processed.
RESTORE DATABASE successfully processed 29426 pages in 4.474 seconds (51.382 MB/sec).
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:01:07.918

Step 2: Create the table

Create a table with 3.7 million rows to be able to show the different in log growth and rollback times.

Depending on the speed of your server, enlarging the database and data could take several minutes.

In [36]:
IF DB_NAME() != 'WideWorldImportersDW' 
USE WideWorldImportersDW
SET NOCOUNT ON
GO

IF EXISTS (SELECT [object_id] FROM sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(N'[Fact].[OrderHistory]') AND [type] IN (N'U'))
DROP TABLE [Fact].[OrderHistory];
GO

IF NOT EXISTS (SELECT [object_id] FROM sys.objects (NOLOCK) WHERE [object_id] = OBJECT_ID(N'[Fact].[OrderHistory]') AND [type] IN (N'U'))
BEGIN
    SELECT [Order Key], [City Key], [Customer Key], [Stock Item Key], [Order Date Key], [Picked Date Key], [Salesperson Key], [Picker Key], [WWI Order ID], [WWI Backorder ID], [Description], Package, Quantity, [Unit Price], [Tax Rate], [Total Excluding Tax], [Tax Amount], [Total Including Tax], [Lineage Key]
    INTO [Fact].[OrderHistory]
    FROM [Fact].[Order];
END;

ALTER TABLE [Fact].[OrderHistory]
ADD CONSTRAINT PK_Fact_OrderHistory PRIMARY KEY CLUSTERED([Order Key] ASC, [Order Date Key] ASC) WITH (DATA_COMPRESSION = PAGE);
GO

-- Enlarge Table
IF (SELECT COUNT(*) FROM [Fact].[OrderHistory]) < 3702592
BEGIN
	DECLARE @i smallint
	SET @i = 0
	WHILE @i < 4
	BEGIN
		INSERT INTO [Fact].[OrderHistory] ([City Key], [Customer Key], [Stock Item Key], [Order Date Key], [Picked Date Key], [Salesperson Key], [Picker Key], [WWI Order ID], [WWI Backorder ID], Description, Package, Quantity, [Unit Price], [Tax Rate], [Total Excluding Tax], [Tax Amount], [Total Including Tax], [Lineage Key])
		SELECT [City Key], [Customer Key], [Stock Item Key], [Order Date Key], [Picked Date Key], [Salesperson Key], [Picker Key], [WWI Order ID], [WWI Backorder ID], Description, Package, Quantity, [Unit Price], [Tax Rate], [Total Excluding Tax], [Tax Amount], [Total Including Tax], [Lineage Key]
		FROM [Fact].[OrderHistory];

		SET @i = @i +1
	END;
END
GO
Commands completed successfully.
Commands completed successfully.
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:01:25.068

Step 2: Delete all the rows in the table

Delete all the rows in the table in a user defined transaction

In [37]:
USE master
GO
ALTER DATABASE WideWorldImportersDW SET ACCELERATED_DATABASE_RECOVERY = OFF
GO

USE WideWorldImportersDW
GO
BEGIN TRAN
DELETE FROM [Fact].[OrderHistory]
GO
Commands completed successfully.
Commands completed successfully.
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:00:29.702

Step 3: Check how much transaction log space is used

Because there is an active transaction the transaction log will have space used that cannot be truncated

In [38]:
SELECT * FROM sys.dm_db_log_space_usage
GO
Out [38]:
Commands completed successfully.
Total execution time: 00:00:00.012
database_idtotal_log_size_in_bytesused_log_space_in_bytesused_log_space_in_percentlog_space_in_bytes_since_last_backup
84294959104281081856065.4446825794560

Step 4: Does a checkpoint truncate the transaction log?

Compare the used_log_space_in_percent to the value from the previous step. Normally for a database with simple recovery a CHECKPOINT would truncate the log.

In [39]:
CHECKPOINT
GO
SELECT * FROM sys.dm_db_log_space_usage
GO
Out [39]:
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:00:03.760
database_idtotal_log_size_in_bytesused_log_space_in_bytesused_log_space_in_percentlog_space_in_bytes_since_last_backup
84294959104281085542465.44545825262080

Step 5: How long does it take to rollback all the deletes

Try to rollback the transation and measure the time it takes

In [40]:
ROLLBACK TRAN
GO
Commands completed successfully.
Total execution time: 00:01:23.086

Step 6: What is the log space usage after a CHECKPOINT

Because the active transaction is rolled back, a CHECKPOINT will allow the log to be truncated.

In [41]:
CHECKPOINT
GO
SELECT * FROM sys.dm_db_log_space_usage
GO
Out [41]:
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:00:01.956
database_idtotal_log_size_in_bytesused_log_space_in_bytesused_log_space_in_percentlog_space_in_bytes_since_last_backup
8429495910498195865622.86305783413248

Step 7: Turn on Accelerated Database Recovery

Note: If you prefer to enable ADR in the existing database file in the PRIMARY filegroup, just execute the last ALTER DATABASE without the ( PERSISTENT_VERSION_STORE_FILEGROUP = [PVS]) statement.

In [42]:
USE master
GO
-- Add a new filegroup specific for the Persistent Version Store (optional)
ALTER DATABASE [WideWorldImportersDW] ADD FILEGROUP [PVS]
GO

DECLARE @adrdatafilepath VARCHAR(8000) = CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS VARCHAR(4000)) + 'ADR.mdf'
DECLARE @sqlcmd VARCHAR(8000) = 'ALTER DATABASE [WideWorldImportersDW] ADD FILE ( NAME = N''ADR'', FILENAME = ''' + @adrdatafilepath + ''', SIZE = 1GB , FILEGROWTH = 65536KB ) TO FILEGROUP [PVS]'
EXEC (@sqlcmd)
GO

-- Enable ADR
ALTER DATABASE WideWorldImportersDW SET ACCELERATED_DATABASE_RECOVERY = ON ( PERSISTENT_VERSION_STORE_FILEGROUP = [PVS])
GO
Commands completed successfully.
Commands completed successfully.
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:00:00.246

Step 8: Try to delete all the rows again under a transaction

In [43]:
USE WideWorldImportersDW
GO
BEGIN TRAN
DELETE FROM [Fact].[OrderHistory]
GO
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:01:02.286

Step 9: Check log space usage before and after a CHECKPOINT

Notice the space used for the log is lower even before the CHECKPOINT. This is because an active transaction does not affect log truncation when using Accelerated Database Recovery.

In [44]:
SELECT * FROM sys.dm_db_log_space_usage
GO
CHECKPOINT
GO
SELECT * FROM sys.dm_db_log_space_usage
GO
Out [44]:
Commands completed successfully.
database_idtotal_log_size_in_bytesused_log_space_in_bytesused_log_space_in_percentlog_space_in_bytes_since_last_backup
84294959104208547840048.556421794609152
Commands completed successfully.
Commands completed successfully.
Total execution time: 00:00:03.640
database_idtotal_log_size_in_bytesused_log_space_in_bytesused_log_space_in_percentlog_space_in_bytes_since_last_backup
84294959104129997619230.267491011310592

Step 10: How fast is a rollback?

See if a rollback is any faster with Accelerated Database Recovery

In [45]:
ROLLBACK TRAN
GO
Commands completed successfully.
Total execution time: 00:00:00.021

It is noticeably faster: 21ms with ADR vs 1m 23s without ADR