Database Mirroring Setup GUI Bug

I came across a bug while testing the setup of Database Mirroring on SQL Server 2016 Standard Edition with SP1 and using the newest version of SQL Server SQL Server Management Studio: v17.8.1
 

Firstly, the preparation went fine.
 
Create the database on the Principal and perform both a Full and Transaction Log Backup of the new database.
 
CREATE DATABASE db1;
BACKUP DATABASE db1 TO DISK = 'C:\SQLBackups\db1.bak';
BACKUP LOG db1 TO DISK = 'C:\SQLBackups\db1.trn';

 

Next restore the backups on the Mirror.
 
RESTORE DATABASE db1 FROM DISK='\\SQL2K16SEP1\SQLBackups$\db1.bak' WITH NORECOVERY;
RESTORE LOG db1 FROM DISK='\\SQL2K16SEP1\SQLBackups$\db1.trn' WITH NORECOVERY;

 

The firewall Inbound Rules for both SQL / Mirroring were added on the Principal and Mirror.
 

Good so all the prep work is done, lets proceed to setup Mirroring using the Wizard on Principal.
 

Go through the Configure Security steps.
 








Bang you get the following 927 error:
Database ‘db1’ cannot be opened. It is in the middle of a restore. (Microsoft SQL Server, Error: 927)
 

So, what is going on here?
 
Looking at Profiler during the setup we see that the GUI issues a use [db1] on the Mirror instance and of course that is going to end badly as the database is not accessible and hence you get the error that ‘db1’ cannot be opened. Microsoft needs to update the GUI to use [master].
 

So how do you resolve this?
 
Well you need to complete the Database Mirroring setup manually and the steps are:
 
1.) On the Mirror use the following to set the principal as a partner:
ALTER DATABASE [db1] SET PARTNER = 'TCP://SQL2K16SEP1:5022';
 

2.) Then finally on the Principal use the following to set the mirror as a partner:
 
ALTER DATABASE [db1] SET PARTNER = 'TCP://SQL2K16SEDR1:5022';
 

Database Mirroring should now be working.
 

I’m sure Microsoft will address this issue in a future release of SSMS, but until then the above should hopefully assist you until then.

August 2018 Critical Patch For SQL Server 2016 / 17

In-case you missed it CVE-2018-8273 | Microsoft SQL Server Remote Code Execution Vulnerability was released yesterday,was marked as Critical and affects SQL Server 2016 & 2017

Further information and downloads can be found here. It should be included in the next SQL Server patching cycle.

If you’re rolling out new servers, you may want to apply it now.

Update: There was an issue with this patch and it has since been replaced

SQL Server 2017 CU 9 Whats New

This is a bit late, but below are the changes detected between CU 8 and CU 9:

The view sys.dm_hadr_availability_replica_states has a new column called write_lease_remaining_ticks

The Microsoft documentation doesn’t mention this column yet, but the below new messages do give an idea on why it has been added.

The following messages have been added:

Message ID Severity Is Event Logged Text
47115 16 No The ‘%ls’ option is not valid for WSFC availability group ‘%.*ls’. Remove the option or set the ‘CLUSTER_TYPE’ option to a different value, then retry the operation.
47116 16 No The external lease cannot be set on availability group ‘%.*ls’. External Lease updates are not enabled for this availability group.
47117 16 No The ‘%ls’ option must be specified with a valid time value when updating the Availability Group’s external write lease status on availability group ‘%.*ls’.
47118 16 No The ‘%ls’ option must be specified with a valid value when updating the external lease status on availability group ‘%.*ls’.
47119 16 No The current write lease of the availability group ‘%.*ls’ is still valid. The lease expiration time cannot be set to an earlier time than its current value.

 

The following Module changes occurred:

sys.dm_hadr_availability_replica_states now includes a reference to the new write_lease_remaining_ticks

sys.sp_vupgrade_replsecurity_metadata has moved away from using the legacy dbo.sysdatabases and now uses sys.databases and excludes database snapshots from its check

New Old
CREATE VIEW sys.dm_hadr_availability_replica_states AS
SELECT
ars.replica_id,
ars.group_id,
ars.is_local,
ars.role,
ars.role_desc,
ars.operational_state,
ars.operational_state_desc,
ars.connected_state,
ars.connected_state_desc,
recovery_health = CASE
WHEN dbs.database_state_aggr IS NULL THEN NULL
WHEN ars.configured_database_count > dbs.database_count THEN CAST (0 AS TINYINT) — ONLINE_IN_PROGRESS
WHEN dbs.database_state_aggr = 0 THEN CAST (1 AS TINYINT) — ONLINE
ELSE CAST (0 AS TINYINT) END, — ONLINE_IN_PROGRESS
recovery_health_desc = CASE
WHEN dbs.database_state_aggr IS NULL THEN CAST (NULL AS NVARCHAR(60))
WHEN ars.configured_database_count > dbs.database_count THEN CAST (‘ONLINE_IN_PROGRESS’ AS NVARCHAR(60))
WHEN dbs.database_state_aggr = 0 THEN CAST (‘ONLINE’ AS NVARCHAR(60))
ELSE CAST (‘ONLINE_IN_PROGRESS’ AS NVARCHAR(60)) END,
synchronization_health = CASE
WHEN (war.availability_mode = 4 AND ars.connected_state = 1) THEN CAST (2 AS TINYINT) — Configuration-only, always healthy when connected
WHEN dbs.synchronization_health_aggr IS NULL THEN CAST (0 AS TINYINT) — NOT_HEALTHY
WHEN ars.configured_database_count > dbs.database_count THEN CAST (0 AS TINYINT) — NOT_HEALTHY (one or more DBs not joined)
ELSE CAST (dbs.synchronization_health_aggr AS TINYINT) END,
synchronization_health_desc = CASE
WHEN (war.availability_mode = 4 AND ars.connected_state = 1) THEN CAST (‘HEALTHY’ AS NVARCHAR(60))
WHEN dbs.synchronization_health_aggr IS NULL THEN CAST (‘NOT_HEALTHY’ AS NVARCHAR(60))
WHEN ars.configured_database_count > dbs.database_count THEN CAST (‘NOT_HEALTHY’ AS NVARCHAR(60))
WHEN dbs.synchronization_health_aggr = 2 THEN CAST (‘HEALTHY’ AS NVARCHAR(60))
WHEN dbs.synchronization_health_aggr = 1 THEN CAST (‘PARTIALLY_HEALTHY’ AS NVARCHAR(60))
ELSE CAST (‘NOT_HEALTHY’ AS NVARCHAR(60)) END,
ars.last_connect_error_number,
ars.last_connect_error_description,
ars.last_connect_error_timestamp,
ars.write_lease_remaining_ticks
FROM
sys.dm_hadr_internal_availability_replica_states ars
LEFT OUTER JOIN
(
SELECT
replica_id,
database_count = COUNT (*),
synchronization_health_aggr = MIN (synchronization_health),
database_state_aggr = MAX (database_state)
FROM
sys.dm_hadr_database_replica_states
GROUP BY replica_id
)
AS dbs
ON (ars.real_replica_id = dbs.replica_id)
LEFT OUTER JOIN
(
SELECT
ag_replica_id,
availability_mode
FROM
sys.dm_hadr_internal_wsfc_ag_replicas
)
AS war
ON (ars.real_replica_id = war.ag_replica_id)
CREATE VIEW sys.dm_hadr_availability_replica_states AS
SELECT
ars.replica_id,
ars.group_id,
ars.is_local,
ars.role,
ars.role_desc,
ars.operational_state,
ars.operational_state_desc,
ars.connected_state,
ars.connected_state_desc,
recovery_health = CASE
WHEN dbs.database_state_aggr IS NULL THEN NULL
WHEN ars.configured_database_count > dbs.database_count THEN CAST (0 AS TINYINT) — ONLINE_IN_PROGRESS
WHEN dbs.database_state_aggr = 0 THEN CAST (1 AS TINYINT) — ONLINE
ELSE CAST (0 AS TINYINT) END, — ONLINE_IN_PROGRESS
recovery_health_desc = CASE
WHEN dbs.database_state_aggr IS NULL THEN CAST (NULL AS NVARCHAR(60))
WHEN ars.configured_database_count > dbs.database_count THEN CAST (‘ONLINE_IN_PROGRESS’ AS NVARCHAR(60))
WHEN dbs.database_state_aggr = 0 THEN CAST (‘ONLINE’ AS NVARCHAR(60))
ELSE CAST (‘ONLINE_IN_PROGRESS’ AS NVARCHAR(60)) END,
synchronization_health = CASE
WHEN (war.availability_mode = 4 AND ars.connected_state = 1) THEN CAST (2 AS TINYINT) — Configuration-only, always healthy when connected
WHEN dbs.synchronization_health_aggr IS NULL THEN CAST (0 AS TINYINT) — NOT_HEALTHY
WHEN ars.configured_database_count > dbs.database_count THEN CAST (0 AS TINYINT) — NOT_HEALTHY (one or more DBs not joined)
ELSE CAST (dbs.synchronization_health_aggr AS TINYINT) END,
synchronization_health_desc = CASE
WHEN (war.availability_mode = 4 AND ars.connected_state = 1) THEN CAST (‘HEALTHY’ AS NVARCHAR(60))
WHEN dbs.synchronization_health_aggr IS NULL THEN CAST (‘NOT_HEALTHY’ AS NVARCHAR(60))
WHEN ars.configured_database_count > dbs.database_count THEN CAST (‘NOT_HEALTHY’ AS NVARCHAR(60))
WHEN dbs.synchronization_health_aggr = 2 THEN CAST (‘HEALTHY’ AS NVARCHAR(60))
WHEN dbs.synchronization_health_aggr = 1 THEN CAST (‘PARTIALLY_HEALTHY’ AS NVARCHAR(60))
ELSE CAST (‘NOT_HEALTHY’ AS NVARCHAR(60)) END,
ars.last_connect_error_number,
ars.last_connect_error_description,
ars.last_connect_error_timestamp
FROM
sys.dm_hadr_internal_availability_replica_states ars
LEFT OUTER JOIN
(
SELECT
replica_id,
database_count = COUNT (*),
synchronization_health_aggr = MIN (synchronization_health),
database_state_aggr = MAX (database_state)
FROM
sys.dm_hadr_database_replica_states
GROUP BY replica_id
)
AS dbs
ON (ars.real_replica_id = dbs.replica_id)
LEFT OUTER JOIN
(
SELECT
ag_replica_id,
availability_mode
FROM
sys.dm_hadr_internal_wsfc_ag_replicas
)
AS war
ON (ars.real_replica_id = war.ag_replica_id)
CREATE PROCEDURE sys.sp_vupgrade_replsecurity_metadata
AS
BEGIN
SET NOCOUNT ON

DECLARE @retcode int,
@statement nvarchar(4000),
@database nvarchar(512),
@has_dbaccess bit,
@is_distributiondb bit,
@is_subscriberdb bit,
@is_upgraded bit
,@agentname nvarchar(100)
,@description nvarchar(100)
,@category_name sysname
,@dbname sysname

— Security Check
IF ISNULL(IS_SRVROLEMEMBER(‘sysadmin’), 0) = 0
BEGIN
— “Only members of the sysadmin fixed server role can perform this operation.”
RAISERROR(21089,16,-1)
RETURN 1
END

IF LOWER(DB_NAME()) != N’master’
BEGIN
— “sp_vupgrade_replsecurity_metadata can only be executed in the master database.”
RAISERROR (21482, 16, -1, ‘sp_vupgrade_replsecurity_metadata’, ‘master’)
RETURN 1
END

— make sure user has already upgraded msdb
IF NOT EXISTS(SELECT *
FROM msdb.sys.columns
WHERE object_id = OBJECT_ID(N’msdb.dbo.sysjobsteps’)
AND name = N’step_uid’)
BEGIN
— “The replication %s could not be upgraded for %s database(s). Please ensure that %s is upgraded and re-execute %s.”
RAISERROR(21450, 16, -1, ‘security meta-data’, ‘all’, ‘msdb database’, ‘sp_vupgrade_replsecurity_metadata’)
RETURN 1
END

BEGIN TRANSACTION
SAVE TRANSACTION tr_upgrade_security_meta

DECLARE cursorDatabases CURSOR LOCAL FAST_FORWARD FOR
SELECT DISTINCT HAS_DBACCESS(name),
sys.fn_MSrepl_isdistdb(name),
N'[‘ + replace(name, N’]’, N’]]’) + N’]’,
name
FROM master.sys.databases
WHERE name NOT IN ( N’master’ COLLATE DATABASE_DEFAULT,
N’tempdb’ COLLATE DATABASE_DEFAULT,
N’msdb’ COLLATE DATABASE_DEFAULT,
N’model’ COLLATE DATABASE_DEFAULT
) and source_database_id is null — exclude DB snapshots
FOR READ ONLY

OPEN cursorDatabases

FETCH cursorDatabases INTO @has_dbaccess, @is_distributiondb, @database, @dbname

WHILE @@FETCH_STATUS != -1
BEGIN
IF @has_dbaccess = 1
BEGIN
— if this is a distribution db then upgrade dist meta-data
IF @is_distributiondb = 1
BEGIN
SELECT @statement = N’SELECT @is_upgraded = 0 ‘ +
N’IF EXISTS(SELECT * ‘+
N’ FROM ‘ + @database + N’.sys.columns ‘ +
N’ WHERE name = N”job_step_uid”) ‘ +
N’BEGIN ‘ +
N’ SELECT @is_upgraded = 1 ‘ +
N’END’

EXEC @retcode = sys.sp_executesql @statement = @statement,
@params = N’@is_upgraded bit OUTPUT’,
@is_upgraded = @is_upgraded OUTPUT
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO

IF @is_upgraded = 1
BEGIN
SELECT @statement = @database + N’.[sys].[sp_MSupgrade_distdb_security_metadata]’

EXEC @retcode = @statement
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO
END
ELSE
BEGIN
— “The replication %s could not be upgraded for %s database(s). Please ensure that %s is upgraded and re-execute %s.”
RAISERROR(21450, 10, -1, ‘distributor security meta-data’, @database, @database, ‘sp_vupgrade_replsecurity_metadata’) WITH NOWAIT
END

— Add replmonitor refresh job for this distribution database

select @agentname = formatmessage (20811, @dbname)
select @description = @agentname
,@statement = N’exec dbo.sp_replmonitorrefreshjob ‘
if not exists (select * from msdb.dbo.sysjobs_view where name = @agentname collate database_default and
upper(originating_server collate database_default) = upper(convert(sysname, SERVERPROPERTY(‘ServerName’)))
and master_server = 0)
BEGIN
select @category_name = name FROM msdb.dbo.syscategories where category_id = 18
EXECUTE @retcode = msdb.sys.sp_MSadd_repl_job @agentname,
@subsystem = ‘TSQL’,
@server = @@SERVERNAME,
@databasename = @dbname,
@description = @description,
@freqtype = 64, — continuous
@freqsubtype = 0, — unused
@freqsubinterval = 0, — unused
@command = @statement,
@retryattempts = 0,
@enabled = 0,
@loghistcompletionlevel = 0,
@category_name = @category_name
if @@ERROR <> 0 or @retcode <> 0
GOTO UNDO
END
END

SELECT @statement = N’SELECT @is_subscriberdb = 0 ‘ +
N’IF EXISTS(SELECT * ‘ +
N’ FROM ‘ + @database + N’.sys.objects ‘ +
N’ WHERE name = N”MSsubscription_properties”) ‘ +
N’BEGIN ‘ +
N’ SELECT @is_subscriberdb = 1 ‘ +
N’END ‘ +
N’SELECT @is_upgraded = 0 ‘ +
N’IF EXISTS(SELECT * ‘ +
N’ FROM ‘ + @database + N’.sys.columns ‘ +
N’ WHERE name = N”job_step_uid”) ‘ +
N’BEGIN ‘ +
N’ SELECT @is_upgraded = 1 ‘ +
N’END’

EXEC @retcode = sys.sp_executesql @statement = @statement,
@params = N’@is_subscriberdb bit OUTPUT, @is_upgraded bit OUTPUT’,
@is_subscriberdb = @is_subscriberdb OUTPUT,
@is_upgraded = @is_upgraded OUTPUT
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO

IF @is_subscriberdb = 1
BEGIN
IF @is_upgraded = 1
BEGIN
— always assume this is subscriber db and attempt upgrade sub meta-data
SELECT @statement = @database + N’.[sys].[sp_MSupgrade_subdb_security_metadata]’

EXEC @retcode = @statement
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO
END
ELSE
BEGIN
— “The replication %s could not be upgraded for %s database(s). Please ensure that %s is upgraded and re-execute %s.”
RAISERROR(21450, 10, -1, ‘subscriber security meta-data’, @database, @database, ‘sp_vupgrade_replsecurity_metadata’) WITH NOWAIT
END
END
END
ELSE
BEGIN
— “Could not open database %s. Upgrade of replication %s could not be performed. Please rerun %s from %s database once the %s is accessible.”
RAISERROR(21733, 10, -1, @database, ‘security meta-data’, ‘sp_vupgrade_replsecurity_metadata’, ‘[master]’, @database) WITH NOWAIT
END

FETCH cursorDatabases INTO @has_dbaccess, @is_distributiondb, @database, @dbname
END

CLOSE cursorDatabases
DEALLOCATE cursorDatabases

COMMIT TRANSACTION tr_upgrade_security_meta

RETURN 0
UNDO:
ROLLBACK TRANSACTION tr_upgrade_security_meta
COMMIT TRANSACTION

RETURN 1
END

CREATE PROCEDURE sys.sp_vupgrade_replsecurity_metadata
AS
BEGIN
SET NOCOUNT ON

DECLARE @retcode int,
@statement nvarchar(4000),
@database nvarchar(512),
@has_dbaccess bit,
@is_distributiondb bit,
@is_subscriberdb bit,
@is_upgraded bit
,@agentname nvarchar(100)
,@description nvarchar(100)
,@category_name sysname
,@dbname sysname

— Security Check
IF ISNULL(IS_SRVROLEMEMBER(‘sysadmin’), 0) = 0
BEGIN
— “Only members of the sysadmin fixed server role can perform this operation.”
RAISERROR(21089,16,-1)
RETURN 1
END

IF LOWER(DB_NAME()) != N’master’
BEGIN
— “sp_vupgrade_replsecurity_metadata can only be executed in the master database.”
RAISERROR (21482, 16, -1, ‘sp_vupgrade_replsecurity_metadata’, ‘master’)
RETURN 1
END

— make sure user has already upgraded msdb
IF NOT EXISTS(SELECT *
FROM msdb.sys.columns
WHERE object_id = OBJECT_ID(N’msdb.dbo.sysjobsteps’)
AND name = N’step_uid’)
BEGIN
— “The replication %s could not be upgraded for %s database(s). Please ensure that %s is upgraded and re-execute %s.”
RAISERROR(21450, 16, -1, ‘security meta-data’, ‘all’, ‘msdb database’, ‘sp_vupgrade_replsecurity_metadata’)
RETURN 1
END

BEGIN TRANSACTION
SAVE TRANSACTION tr_upgrade_security_meta

DECLARE cursorDatabases CURSOR LOCAL FAST_FORWARD FOR
SELECT DISTINCT HAS_DBACCESS(name),
sys.fn_MSrepl_isdistdb(name),
N'[‘ + replace(name, N’]’, N’]]’) + N’]’,
name
FROM master.dbo.sysdatabases
WHERE name NOT IN ( N’master’ COLLATE DATABASE_DEFAULT,
N’tempdb’ COLLATE DATABASE_DEFAULT,
N’msdb’ COLLATE DATABASE_DEFAULT,
N’model’ COLLATE DATABASE_DEFAULT
)
FOR READ ONLY

OPEN cursorDatabases

FETCH cursorDatabases INTO @has_dbaccess, @is_distributiondb, @database, @dbname

WHILE @@FETCH_STATUS != -1
BEGIN
IF @has_dbaccess = 1
BEGIN
— if this is a distribution db then upgrade dist meta-data
IF @is_distributiondb = 1
BEGIN
SELECT @statement = N’SELECT @is_upgraded = 0 ‘ +
N’IF EXISTS(SELECT * ‘+
N’ FROM ‘ + @database + N’.sys.columns ‘ +
N’ WHERE name = N”job_step_uid”) ‘ +
N’BEGIN ‘ +
N’ SELECT @is_upgraded = 1 ‘ +
N’END’

EXEC @retcode = sys.sp_executesql @statement = @statement,
@params = N’@is_upgraded bit OUTPUT’,
@is_upgraded = @is_upgraded OUTPUT
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO

IF @is_upgraded = 1
BEGIN
SELECT @statement = @database + N’.[sys].[sp_MSupgrade_distdb_security_metadata]’

EXEC @retcode = @statement
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO
END
ELSE
BEGIN
— “The replication %s could not be upgraded for %s database(s). Please ensure that %s is upgraded and re-execute %s.”
RAISERROR(21450, 10, -1, ‘distributor security meta-data’, @database, @database, ‘sp_vupgrade_replsecurity_metadata’) WITH NOWAIT
END

— Add replmonitor refresh job for this distribution database

select @agentname = formatmessage (20811, @dbname)
select @description = @agentname
,@statement = N’exec dbo.sp_replmonitorrefreshjob ‘
if not exists (select * from msdb.dbo.sysjobs_view where name = @agentname collate database_default and
upper(originating_server collate database_default) = upper(convert(sysname, SERVERPROPERTY(‘ServerName’)))
and master_server = 0)
BEGIN
select @category_name = name FROM msdb.dbo.syscategories where category_id = 18
EXECUTE @retcode = msdb.sys.sp_MSadd_repl_job @agentname,
@subsystem = ‘TSQL’,
@server = @@SERVERNAME,
@databasename = @dbname,
@description = @description,
@freqtype = 64, — continuous
@freqsubtype = 0, — unused
@freqsubinterval = 0, — unused
@command = @statement,
@retryattempts = 0,
@enabled = 0,
@loghistcompletionlevel = 0,
@category_name = @category_name
if @@ERROR <> 0 or @retcode <> 0
GOTO UNDO
END
END

SELECT @statement = N’SELECT @is_subscriberdb = 0 ‘ +
N’IF EXISTS(SELECT * ‘ +
N’ FROM ‘ + @database + N’.sys.objects ‘ +
N’ WHERE name = N”MSsubscription_properties”) ‘ +
N’BEGIN ‘ +
N’ SELECT @is_subscriberdb = 1 ‘ +
N’END ‘ +
N’SELECT @is_upgraded = 0 ‘ +
N’IF EXISTS(SELECT * ‘ +
N’ FROM ‘ + @database + N’.sys.columns ‘ +
N’ WHERE name = N”job_step_uid”) ‘ +
N’BEGIN ‘ +
N’ SELECT @is_upgraded = 1 ‘ +
N’END’

EXEC @retcode = sys.sp_executesql @statement = @statement,
@params = N’@is_subscriberdb bit OUTPUT, @is_upgraded bit OUTPUT’,
@is_subscriberdb = @is_subscriberdb OUTPUT,
@is_upgraded = @is_upgraded OUTPUT
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO

IF @is_subscriberdb = 1
BEGIN
IF @is_upgraded = 1
BEGIN
— always assume this is subscriber db and attempt upgrade sub meta-data
SELECT @statement = @database + N’.[sys].[sp_MSupgrade_subdb_security_metadata]’

EXEC @retcode = @statement
IF @@ERROR <> 0 OR @retcode <> 0
GOTO UNDO
END
ELSE
BEGIN
— “The replication %s could not be upgraded for %s database(s). Please ensure that %s is upgraded and re-execute %s.”
RAISERROR(21450, 10, -1, ‘subscriber security meta-data’, @database, @database, ‘sp_vupgrade_replsecurity_metadata’) WITH NOWAIT
END
END
END
ELSE
BEGIN
— “Could not open database %s. Upgrade of replication %s could not be performed. Please rerun %s from %s database once the %s is accessible.”
RAISERROR(21733, 10, -1, @database, ‘security meta-data’, ‘sp_vupgrade_replsecurity_metadata’, ‘[master]’, @database) WITH NOWAIT
END

FETCH cursorDatabases INTO @has_dbaccess, @is_distributiondb, @database, @dbname
END

CLOSE cursorDatabases
DEALLOCATE cursorDatabases

COMMIT TRANSACTION tr_upgrade_security_meta

RETURN 0
UNDO:
ROLLBACK TRANSACTION tr_upgrade_security_meta
COMMIT TRANSACTION

RETURN 1
END

 

That’s all folks.

SQL Server 2017 CU8 has been released

With the release of CU8 (build 14.0.3029.16)  today, AM detected the following changes since CU7:

New Messages

Message ID Severity Is Event Logged Text
997 16 No Failed to get the update lock on database ‘%.*ls’.
12623 10 No Clone backup succeeded and is stored in %ls.
12624 10 No Clone backup failed.
12625 10 No RESTORE VERIFY failed on the clone backup %ls
12626 10 No Clone database verification has passed.
12627 10 No Clone database verification has failed.
12628 10 No NO_STATISTICS and NO_QUERYSTORE options turned ON as part of VERIFY_CLONE.
12629 10 No Database ‘%.*ls’ is a cloned database.
12630 16 No VERIFY_CLONE option cannot be specified together with SERVICEBROKER option.
33331 16 No DBCC CLEANUPCONVERSATIONS is not allowed on this server.
33332 16 No DBCC CLEANUPCONVERSATIONS cannot be executed through MARS connection.
41870 10 No Dropped %d Orphan Internal Table(s).

Further info on DBCC CLONEDATABASE can be found here.

Changed Message

Message ID New Text Old Text
12621 Database ‘%.*ls’ is a cloned database. This database should be used for diagnostic purposes only and is not supported for use in a production environment. Database ‘%.*ls’ is a cloned database. A cloned database should be used for diagnostic purposes only and is not supported for use in a production environment.

Small wording change.

New configuration option ‘column encryption enclave type’

Just noticed that AM picked up a new configuration in Azure SQL Database called column encryption enclave type.

This option is not currently documented and currently:

  • Configuration ID = 1588
  • Default = 0
  • Minimum = 0
  • Maximum = 3
  • It is not a Dynamic or Advanced configuration setting
  • Description is ‘Type of enclave used for computations on encrypted columns’



This is likely related to Always Encrypted using enclaves early access technology preview.

Introducing YDBOLO

Having had zero web development experience I thought now is a good a time as any to tip my toe and bang Your Database Only Lives Once (YDBOLO) was born.

https://ydbolo.azurewebsites.net

Simply connect to your SQL Azure Database with a login which has VIEW DATABASE STATE and you’ll get some summary info, chart performance and active query info.

Beta version 0.0000000 was released today.

SQL Server 2016 SP1 CU9 & SP2 CU1 Released

Notification of SQL Server 2016 SP1 CU9 (build 13.0.4502.0) and SP2 CU 1 (build 13.0.5149.0) releases was made today.

AKAWN Monitoring detected the following change between SP2 and SP2 CU1.

Modules

Name New Old
sys.sp_flush_commit_table_on_demand CREATE PROC sys.sp_flush_commit_table_on_demand (@numrows as BIGINT = NULL, @deleted_rows BIGINT = NULL OUTPUT, @date_cleanedup DATETIME = NULL OUTPUT, @cleanup_ts BIGINT = NULL OUTPUT) AS
BEGINIF (is_srvrolemember(‘sysadmin’) = 0)
BEGIN
raiserror(21089,0,1)
return 1
END

IF (@numrows<=0)
BEGIN
raiserror(23100,0,1)
return 1
END

SET DEADLOCK_PRIORITY LOW

IF EXISTS (SELECT * FROM sys.change_tracking_databases where database_id = DB_ID())
BEGIN
DECLARE @batch_size INT
IF (@numrows IS NULL or @numrows >= 10000)
SET @batch_size = 10000
ELSE
SET @batch_size = @numrows

— checking for change tracking side table watermark
DECLARE @deleted_rowcount INT
SET @cleanup_ts = change_tracking_hardened_cleanup_version ()
RAISERROR(22866,0,1,35502,@cleanup_ts)

— checking for safe cleanup watermark
DECLARE @cleanup_version BIGINT
set @cleanup_version = safe_cleanup_version ()
RAISERROR(22866,0,1,35503,@cleanup_version)

IF @cleanup_ts > @cleanup_version
SET @cleanup_ts = @cleanup_version

SELECT @deleted_rowcount = 0, @deleted_rows = 0

WHILE (1=1)
BEGIN
DELETE TOP(@batch_size) sys.syscommittab WHERE commit_ts < @cleanup_ts
SELECT @deleted_rowcount = @@ROWCOUNT
SELECT @deleted_rows += @deleted_rowcount
SELECT @numrows-=10000
IF ((@numrows IS NOT NULL AND @numrows <= 0 ) OR @deleted_rowcount < 10000)
BREAK;
END

select @date_cleanedup = min(commit_time) from sys.syscommittab where commit_ts = (select min(commit_ts) from sys.syscommittab)
IF (@date_cleanedup is null)
SET @date_cleanedup = GETUTCDATE()
END
ELSE IF EXISTS (SELECT * FROM sys.databases WHERE DB_NAME() not in (‘master’, ‘tempdb’, ‘model’, ‘msdb’, ‘mssqlsystemresource’))
TRUNCATE TABLE sys.syscommittab

END

CREATE PROC sys.sp_flush_commit_table_on_demand (@numrows as BIGINT = NULL, @deleted_rows BIGINT = NULL OUTPUT, @date_cleanedup DATETIME = NULL OUTPUT, @cleanup_ts BIGINT = NULL OUTPUT) AS
BEGINIF (is_srvrolemember(‘sysadmin’) = 0)
BEGIN
raiserror(21089,0,1)
return 1
END

IF (@numrows<=0)
BEGIN
raiserror(23100,0,1)
return 1
END

SET DEADLOCK_PRIORITY LOW

DECLARE @batch_size INT
IF (@numrows IS NULL or @numrows >= 10000)
SET @batch_size = 10000
ELSE
SET @batch_size = @numrows

— checking for change tracking side table watermark
DECLARE @deleted_rowcount INT
SET @cleanup_ts = change_tracking_hardened_cleanup_version ()
RAISERROR(22866,0,1,35502,@cleanup_ts)

— checking for safe cleanup watermark
DECLARE @cleanup_version BIGINT
set @cleanup_version = safe_cleanup_version ()
RAISERROR(22866,0,1,35503,@cleanup_version)

IF @cleanup_ts > @cleanup_version
SET @cleanup_ts = @cleanup_version

SELECT @deleted_rowcount = 0, @deleted_rows = 0

WHILE (1=1)
BEGIN
DELETE TOP(@batch_size) sys.syscommittab WHERE commit_ts < @cleanup_ts
SELECT @deleted_rowcount = @@ROWCOUNT
SELECT @deleted_rows += @deleted_rowcount
SELECT @numrows-=10000
IF ((@numrows IS NOT NULL AND @numrows <= 0 ) OR @deleted_rowcount < 10000)
BREAK;
END

select @date_cleanedup = min(commit_time) from sys.syscommittab where commit_ts = (select min(commit_ts) from sys.syscommittab)
IF (@date_cleanedup is null)
SET @date_cleanedup = GETUTCDATE()
DECLARE @dbname sysname
SET @dbname= DB_NAME()

raiserror(21092,-1,-1,@dbname)

END

SQL Server 2017 CU7 Released

Today SQL Server 2017 CU7 (build 14.0.3026.27) was released.

AKAWN Monitoring detected the following change since CU6.

Message ID New Old
833 SQL Server has encountered %d occurrence(s) of I/O requests taking longer than %d seconds to complete on file [%ls] in database id %d.  The OS file handle is 0x%p.  The offset of the latest long I/O is: %#016I64x.  The duration of the long I/O is: %I64u ms. SQL Server has encountered %d occurrence(s) of I/O requests taking longer than %d seconds to complete on file [%ls] in database id %d.  The OS file handle is 0x%p.  The offset of the latest long I/O is: %#016I64x

So this is a nice add as the long I/O requests now includes the duration in ms.

AKAWN Monitoring version 18.05.07 Released

Today v18.05.07 has been released and it includes 27 updates.
 
One really exciting update is the detection and notification of key Microsoft product changes when a new patch is applied. I suspect this could be really helpful for keeping on top of new functionality added to your Azure SQL Databases.
 
As an example, below were the changes found when the latest SQL Server 2017  CU 6 patch was applied to a SQL Server 2017  CU 5 instance.
 

 
You can also choose to receive these changes as emails: