Nieuwe standaard security in Microsoft OLE DB for SQL Server

Microsoft trekt de security-touwtjes aan! Net als in Microsoft SQL Server Management Studio heeft de driver Microsoft OLE DB for SQL Server vanaf versie 19.0.0 nu ook ‘security-by-default’. Is dat écht nieuw? Nee, deze feature zit er al sinds 15 februari 2022 in toen Microsoft versie 19.0.0 lanceerde. Ik liep er echter deze week tijdens één van mijn installaties tegen aan.

Waar wordt Microsoft OLE DB for SQL Server gebruikt?
Multidimensionale kubusdatabases en tabular models maken gebruik van deze driver om verbinding te maken naar de brondatabase van de analysis server objecten.

Is de security-by-default dan verplicht?
Nee, wanneer in de connection string van de driver Use Encryption for Data=Optional wordt toegevoegd, zal de security worden omzeild. Een voorbeeld connection string:
Provider=MSOLEDBSQL19;Data Source=[Database server];Initial Catalog=[Database];Integrated Security=SSPI;Persist Security Info=false;Use Encryption for Data=Optional

Meer informatie
Meer informatie is beschikbaar in de volgende links (in het Engels)

De database msdb groeit uit z’n voegen!

In de msdb database worden veel processen van microsoft vastgelegd, onder andere systeembrede stored procedures en ook logging van de SQL agent en database mail. Ongemerkt groeit deze database heel snel heel hard en zit deze database in no-time op enkele tientallen gigabyte grootte. Bij goed SQL server beheer hoort dat niet. Die groei moet in de perken worden gehouden.

Waardoor groeit msdb
De groei van de msdb database kent vele oorzaken. De oorzaken die de meeste groei veroorzaken zijn:

  • De historie van SQL agent jobs
  • De logs van database mail
  • De logs van backups
  • De logs van logshipping procedures

Wat kunnen we eraan doen?
Wanneer u nog geen onderhoud op de msdb database heeft gepleegd, is het handig om eerst de volgende punten vast te stellen:

  • Hoe groot is de msdb database nu?
  • Hoeveel van die ruimte is er al vrij?
  • Hoe groot is msdb database op de storage?
  • Wat zijn mijn grootste tabellen in de database?

Het vast stellen van de bovenstaande punten kan het makkelijkst via SQL Server Management Studio. Door met de rechtermuis klik op de msdb database te klikken, kan er voor Reports worden gekozen. De relevante rapporten zijn Disk Usage en Disk Usage by Table. Dit geeft een goed beeld van de database. Wanneer de database groter dan 5GB is, wijst dat al op excessieve historische logging. Per tabel kan vervolgens worden gekeken hoeveel records er in de tabel zitten en hoeveel ruimte die tabel in neemt. Met onderstaande query kan bijvoorbeeld worden gekeken hoeveel stappen er per SQL agent job zijn gedraaid in het verleden.

SELECT
	sj.name			AS [SQL Server Agent job],
	count(sjh.step_name)	AS [Aantal stappen in de historie]
FROM dbo.sysjobhistory sjh WITH (NOLOCK)
JOIN dbo.sysjobs sj ON sjh.job_id = sj.job_id
GROUP BY sj.name
ORDER BY sj.name;
[/code>]

<strong>Opschonen historische SQL agent jobs</strong>
Voor het opschonen van historische SQL agent jobs wordt de stored procedure <em>sp_purge_jobhistory</em> gebruikt. Deze stored procedure kan de hele historie van één job opruimen of de historie van alle jobs tot en met een bepaalde datum; of een combinatie hiervan. Globaal kan daar onderstaande query voor worden gebruikt
[code language="sql"]
DECLARE @Peildatum datetime = (SELECT DATEADD(MONTH,-1,GETDATE()))
EXECUTE [msdb].[dbo].[sp_purge_jobhistory]
--	@job_name = 'LSRestore_CS-DT1712014_HiX62_Support',
	@oldest_date = @Peildatum

Opschonen database mail
Voor het opschonen van database mail worden de stored procedures sysmail_delete_log_sp en sysmail_delete_mailitems_sp gebruikt. Voorbeeld query:

DECLARE @Peildatum datetime = (SELECT DATEADD(MONTH,-1,GETDATE()))
EXECUTE sysmail_delete_log_sp @logged_before = @Peildatum
EXECUTE sysmail_delete_mailitems_sp @sent_before = @Peildatum

Opruimen van de logshipping historie
Voor het opschonen van historische backup data wordt de stored procedure sp_delete_backuphistory gebruikt. Voorbeeld query:

DECLARE @Peildatum datetime = (SELECT DATEADD(MONTH,-1,GETDATE()))
EXECUTE sp_delete_backuphistory @oldest_date = @Peildatum

Opruimen van de logshipping historie
Voor het opschonen van historische logshipping data wordt de stored procedure sp_cleanup_log_shipping_history gebruikt.
LET OP: deze stored procedure draait in de master database! Voorbeeld query:

DECLARE @database nvarchar(100)
DECLARE @agent_id nvarchar(100)
DECLARE @agent_type int
DECLARE @NumberOfRecords int

DECLARE agent_cursor CURSOR FOR
	SELECT DISTINCT
		database_name,
		agent_id,
		agent_type,
		COUNT(*) AS NumberOfRecords
	FROM msdb.dbo.log_shipping_monitor_history_detail
	GROUP BY database_name,agent_id,agent_type
--	ORDER BY database_name, agent_id, agent_type

OPEN agent_cursor
FETCH NEXT FROM agent_cursor
INTO @database, @agent_id, @agent_type, @NumberOfRecords

IF @@FETCH_STATUS <> 0
PRINT 'No records'

WHILE @@FETCH_STATUS = 0
BEGIN
execute master.dbo.sp_cleanup_log_shipping_history 
	@agent_id = @agent_id,
	@agent_type = @agent_type;
	FETCH NEXT FROM agent_cursor
	INTO @database, @agent_id, @agent_type, @NumberOfRecords
END

CLOSE agent_cursor
DEALLOCATE agent_cursor

En dan…? De msdb database is nog steeds niet kleiner geworden (op de storage)
Dat klopt! Verwijderen van data uit tabellen zorgt er alleen maar voor dat er ruimte binnen de database vrijkomt, die dan eerst weer hergebruikt wordt. Met de functie SHRINKFILE kan de database ook op de storage kleiner worden gemaakt. De meningen zijn erg verdeeld of het gebruik van de functie SHRINKFILE wél of niet verstandig is. Deze discussie moet u binnen uw eigen organisatie voeren. Ik leg u in deze bijdrage alleen uit, hoe de functie wordt gebruikt. De query’s:

-- We gaan naar de msdb database
USE msdb;
GO

-- We verkleinen eerst de data file
DBCC SHRINKFILE (N'MSDBData' , 500);
GO

-- We verkleinen dan de log file
DBCC SHRINKFILE (N'MSDBLog' , 200);
GO

-- Daarna is het verstandig de indexen opnieuw op te bouwen
EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)";
GO

Het opnieuw indexeren van de tabellen is een belangrijk onderdeel van de procedure om ervoor te zorgen dat eventuele fragmentatie van de database tabellen wordt tegen gegaan.

Nu is de msdb database weer behapbaar. Om dit zo te houden, is mijn advies om alle opruimquery’s in de SQL agent op te nemen en de opruimacties maandelijks uit te voeren. Dat zou uw msdb database in topconditie moeten houden.

Batchverwerking van bestanden met Windows functie ForFiles

Ik ben al langer op zoek naar een manier om bestanden in een batch te verwerken; in het bijzonder het verwijderen van bestanden die meer dan X dagen oud zijn. Tijdens mijn zoektocht kwam ik de Windows functie ForFiles tegen. Het verraste mij dat bij het schrijven van deze bijdrage blijkt dat deze functie als sinds Windows Vista beschikbaar is.

Hoe het werkt
ForFiles werkt met een aantal parameters, die…

  • Alle bestanden in een folder langsloopt
  • Ook in subfolders kan kijken
  • Windows bewerkingen (o.a. DELETE) op deze bestanden kan uitvoeren

Voorbeeld
ForFiles /S /P “[drive]:[Folder]” /D -10 /C “cmd /c del /F /Q @file”

Bovenstaand voorbeeld verwijdert alle bestanden ouder dan 10 dagen uit de betrokken folder en alle onderliggende subfolders.

Meer weten
Onderstaande bijdragen zijn in het Engels en hebben nog wat extra voorbeelden:

SSAS Analysis Server melding Multi-dimensional database is not using latest encryption schema.

Bij het uitrollen van een multi-dimensionale kubussolution krijgt u de melding An error has occurred, please contact your administrator \nErrors in the metadata manager. Multi-dimensional database [kubusdatabase] is not using latest encryption schema. Please create a backup file and restore DB from backup file with the option EnsureProperEncryption to upgrade to the latest encryption..

Dit is een nieuwe functionaliteit in SQL Server 2022. Eenmalig dient er bij deze melding een backup te worden gemaakt van de kubusdatabase en dient deze backup te worden terug gezet waarbij de optie ‘EnsureProperEncryption’ op ‘True’ staat. Is dat eenmaal gebeurt, dan kunnen toekomstige updates van deze kubussolution weer normaal worden uitgerold zonder dat de kubussolution hoeft te worden verwijderd.

Link: Microsoft pagina’s in het Engels die van toepassing zijn.

De LSAlert op de logship database server geeft onterecht een foutmelding!

Het volgende scenario doet zich op de SQL Server database server voor waar de logship database op staat:

  • De LSAlert job geeft aan dat de logship database niet is bijgewerkt en ‘out-of-sync’ is
  • De LSRestore job geeft een groen vinkje om aan te geven dat die job goed heeft gelopen
  • De logship database is bijgewerkt
  • Recente data uit de brondatabase is ook in de logship database zichtbaar en beschikbaar

Maar … de logship database staat op een SQL Server versie die lager is dan de brondatabase. Bijvoorbeeld de logship database draait op SQL Server versie 2016 en de brondatabase draait (al) op SQL Server versie 2022.

Dit kan tot problemen leiden, omdat de database structuur van systeem databases (zoals bijvoorbeeld msdb) waar SQL Server logging naar toe schrijft een andere structuur hebben (bijvoorbeeld nieuwe velden in systeemtabellen of velden die naar andere systeemtabellen zijn verplaatst). Het zou dan kunnen dat de LSRestore job dan gegevens probeert weg te schrijven die in de nieuwere versie van SQL Server niet meer van toepassing zijn of zijn verplaatst.

Valt dit dan nergens op? Tot nu toe heeft SQLTeam een foutmelding in de schijnbaar goed afgeronde LSRestore job gevonden. Namelijk de foutmelding:

*** Error: Could not log history/error message.(Microsoft.SqlServer.Management.LogShipping) ***
*** Error: Failed to convert parameter value from a SqlGuid to a String.(System.Data) ***
*** Error: Object must implement IConvertible.(mscorlib) ***

Het niet kunnen wegschrijven van log historie en foutmeldingen uit bovenstaande melding. Triggert de LSAlert job die van deze logging gebruik maakt om te kijken of een logship database is bijgewerkt. Hoewel de melding uit de LSAlert job dus inderdaad onterecht is, is dat in deze situatie goed te verklaren. Bovenstaande foutmelding doet zich voor wanneer de logship database op een lagere versie draait dan de brondatabase.

Onderstaande foutmelding doet zich voor wanneer de logship database op een hogere versie van SQL Server staat dan de brondatabase.

2024-07-23 03:25:00.87 *** Error: An error occurred restoring the database access mode.(Microsoft.SqlServer.Management.LogShipping) ***
2024-07-23 03:25:00.89 *** Error: Alter failed for Database '[Naam van de logship database]'. (Microsoft.SqlServer.Smo) ***
2024-07-23 03:25:00.89 *** Error: An exception occurred while executing a Transact-SQL statement or batch.(Microsoft.SqlServer.ConnectionInfo) ***
2024-07-23 03:25:00.89 *** Error: Database '[Naam van de logship database]' cannot be opened. It is in the middle of a restore.(.Net SqlClient Data Provider) ***
2024-07-23 03:25:00.92 *** Error: Could not apply log backup file '[Naam en locatie van de transactielog.trn]' to secondary database '[Naam van de logship database]'.(Microsoft.SqlServer.Management.LogShipping) ***
2024-07-23 03:25:00.92 *** Error: This backup cannot be restored using WITH STANDBY because a database upgrade is needed. Reissue the RESTORE without WITH STANDBY.
RESTORE LOG is terminating abnormally.(.Net SqlClient Data Provider) ***

Advies
Zorg ervoor dat de SQL versies van de brondatabase (primary) en de logship databases van die brondatabase(s) (secondary of secondaries) altijd gelijk aan elkaar is om dit soort situaties te voorkomen.

Opeens “Service Unavailable” op een relatief nieuwe Report Server(?)

Is dit bij u aan de hand…

  • U heeft net een nagelnieuwe Report Server opgeleverd gekregen?
  • U maakt verbinding met de Report Server via een internet browser?
  • Dat gaat een paar weken goed, totdat opeens bij het openen van de report server wél de folders worden getoond, maar bij het openen van elk rapport de melding “Service Unavailable” veschijnt?

De waarschijnlijke oorzaak is dat de evaluatie-versie van Report Server is geïnstalleerd. Dit is te controleren door in de folder C:\Program Files\Microsoft SQL Server Reporting Services\SSRS\LogFiles\ (of de folder waar bij u Report Server is geïnstalleerd) het logbestand ReportingServicesService_[datum/tijd].log te openen en te scannen op meldingen.

… En ja … Betrek altijd alle logs van SQL Server bij uw analyses. Ze zijn écht uw beste vrienden.

Foutmelding bij deployen van kubussolutions naar een Microsoft SQL Server Analysis Server

Enige tijd geleden was ik bezig met het deployen van kubussolutions naar een Microsoft SQL Server Analysis Server. Bij het deployen, verscheen de volgende melding An error has occurred, please contact your administrator \nInternal error: An unexpected error occurred (file ‘pcserialize.cpp’, line 1535, function ‘ASDatabase::Serialize’)

“An unexpected error”; typisch Microsoft waar je dus niets mee kunt. Na lang onderzoek bleek de oorzaak eigenlijk heel simpel: in het security tabblad van de server properties waren geen administrators opgenomen; zelfs geen BUILTIN\Administrators. Blijkbaar is het een goed idee om in dat tabblad in ieder geval één account te vermelden. Zo dus…

Na het toevoegen van een administrator in dit tabblad, rolden de kubussolutions wél goed uit.

SQL Server databases – informatie over de restore van een backup

Regelmatig krijg ik de vraag: “Weet jij wanneer de backup van [deze] en [deze] database is gemaakt en wanneer die is teruggezet?”. Het antwoord is ‘ja’… en met deze bijdrage weet u het nu ook. Draai op de SQL Server waar de teruggezette database staat onderstaande query:

SELECT 
   [rs].[destination_database_name], 
   [rs].[restore_date], 
   [bs].[backup_start_date], 
   [bs].[backup_finish_date], 
   [bs].[database_name] as [source_database_name], 
   [bmf].[physical_device_name] as [backup_file_used_for_restore]
FROM msdb..restorehistory rs
INNER JOIN msdb..backupset bs ON [rs].[backup_set_id] = [bs].[backup_set_id]
INNER JOIN msdb..backupmediafamily bmf ON [bs].[media_set_id] = [bmf].[media_set_id] 
ORDER BY [rs].[restore_date] DESC

Zo wordt de gevraagde informatie gevonden.

Met dank aan Thomas LaRock die deze informatie in het Engels in deze bijdrage heeft gedeeld.

Opstarten SQL Server onder ‘Local Service’ account; niet doen!

Bij de installatie van SQL Server wordt de SQL Service onder een zogenaamd local service account gestart. Heel af en toe valt het mij op dat het service account waaronder onderdelen van SQL Server worden gestart, niet naar een domein account wordt gewijzigd. Het is verstandig om de onderdelen van SQL Server onder aparte (!) domein accounts te laten starten; dus een apart domein account voor de database engine, een apart domein account voor de analysis server, één voor de SQL Agent, etc.

Waarom zo moeilijk als het ook makkelijk kan?
Het gebruik van een domein account zorgt ervoor dat op de onderdelen van SQL Server eenvoudiger wijzigingen kunnen worden gemaakt. Afgelopen week kwam ik tegen dat SSAS kubussolutions niet naar een analysis server konden worden uitgerold, omdat er geen gebruik van een domein account werd gemaakt. Bij gebruik van het ‘local service account’ weet het systeem niet of er voldoende rechten zijn bij o.a. het uitrollen van de kubussolutions vanaf een andere machine.

Ok… maar aparte domein accounts voor elk onderdeel van SQL Server?
Hoeft niet, maar het maakt de rechtenstructuur wél duidelijker. Een voorbeeld: om kubussen bij te werken onder het service account waaronder de analysis server wordt gestart, dient dat service account wél leesrechten te hebben op de brondatabase van de database engine; óók wanneer de database engine onder hetzelfde domein account wordt gestart. Het is dan overzichtelijker en duidelijker om de analysis server met een eigen service account te starten.

Kan het nóg scherper / beter?
Ja, door gebruik te maken van “(group) managed service accounts”. Het is wat meer werk, maar heeft als voordeel dat deze accounts uitsluitend kunnen worden gebruikt door de machines die hier rechten voor hebben gekregen. Daarnaast heeft dit account geen wachtwoord, waardoor het account ook niet voor andere doeleinden kan worden gebruikt / misbruikt. Met dank aan mijn collega voor deze mooie aanvulling.

Dus gebruik domein (group) managed service accounts bij het starten van onderdelen van SQL Server in een netwerk met Active Directory als basis.

** SQL Server database compatibility level? Wat is dat? **

Regelmatig komen we databases tegen die op de laatste versie van Microsoft SQL Server draaien en toch niet van de laatste technieken en inzichten gebruik kunnen maken. Met de verhuizing van een SQL Server database naar een nieuwe machine met de laatste SQL Server versie is het nog niet klaar! Dat geldt ook wanneer de SQL Server wordt bijgewerkt met de laatste versie van SQL Server. De betrokken database(s) moet(en) nog worden bijgewerkt!

Microsoft die zorgt ervoor dat een nieuwere versie van SQL Server niet direct impact heeft op de databases die op de SQL Server draaien. Elke database heeft op database niveau in het tabblad ‘Options’ de instelling ‘Compatibility Level’. Deze instelling zorgt ervoor dat de database zich gedraagt zoals die op de ‘oude’ versie van SQL Server is aangemaakt. Dit voorkomt dat de database opeens onder andere performance issues geeft of query plannen maakt, waar de database helemaal niet geschikt voor is.

Wanneer wordt de instelling “Compatibility Level” dan gewijzigd?
Na uitgebreide tests! De best-practice is om een kopie van de database op een testmachine te plaatsen en eerst daar deze instelling naar de hoogste versie te brengen om vervolgens alle relevante query’s en andere processen op de database te testen. Vervolgens kunnen op deze database dan de nodige wijzigingen worden gemaakt (en opnieuw worden getest) om de wijzigingen vervolgens op een geschikt moment in productie te brengen en dan pas in productie de instelling ‘Compatibility Level’ te wijzigen.

Moet de instelling worden gewijzigd?
Nee, het moet niet, voor zolang Microsoft de huidige compatibility level ondersteunt. Of het verstandig is om het niet te doen, is een tweede. Ik kan mij voorstellen dat ook uw organisatie met de laatste inzichten en technieken wilt werken. Dan is het echt noodzakelijk om de tests uit te voeren en uiteindelijk de productie-database naar het juiste niveau te brengen.