WSUS zusammen mit der WID auf Laufwerk D

Fügt man den Windows Server Update Service (WSUS) auf einem Windows Server (2016 oder 2019) hinzu, dann werden weitere für die Rolle notwendigen Dienste und Funktionen hinzugefügt.

image

Darunter auch die Windows Internal Database (WID), als SQL-Server für die Bereitstellung der WSUS-Datenbank.

image

Die WID ist nur zur Verwendung von Windows eigenen Diensten, wie dem WSUS gedacht und nicht zur Bereitstellung von Datenbanken für externe Anwendungen.

Neben dieser Einschränkung hat die WID einen großen Vorteil: Im Gegensatz zur kostenlosen SQL Server Express Edition besitzt sie keine Begrenzung der maximalen Größe einer Datenbank auf 10GB (bis zum SQL Server 2008R2 war das Limit sogar nur 4GB).

Wird der WSUS über PowerShell hinzugefügt, erfolgt ebenfalls die Installation und Verwendung der WID.

image

Hier die Installation über PowerShell:

Install-WindowsFeature UpdateServices -Restart -IncludeManagementTools -Restart

Wird die WID mit dem WSUS verwendet, dann unterliegt dessen Datenbank, die SUSDB, nicht der 10GB Begrenzung wie das bei der Verwendung der SQL Server Express Edition der Fall ist.

Das ist ein Vorteil, da die SUSDB gerne mal die 10GB Grenze, vor allem wenn die Wartung vernachlässigt wird, übersteigt.

Der Haken an der Sache ist, dass die WID nach ihrer Installation auf dem Laufwerk C liegt und dort will ich sie nicht haben.

Umkonfigurieren der WID auf ein anderes Laufwerk

Die WID muss daher nicht auf Laufwerk C verbleiben, sondern kann auf ein anderes Laufwerk gelegt werden. Dazu sind die folgenden Tools und Schritte notwendig.

  • Nachdem der WSUS und damit die WID hinzugefügt wurde, aber noch bevor eine Konfiguration des WSUS erfolgt, sollte die WID auf ein passendes Laufwerk gelegt werden. Ich nehme dazu gerne Laufwerk D, dass ich in Form einer 256GB großen Platte bereitstelle
  • Damit die WID auf Laufwerk D verschoben werden kann, empfiehlt es sich das ohnehin für die Wartung der SUSDB hilfreiche SQL Server Management Studio zu installieren
  • Nicht notwendig, aber für mich immer praktisch ist Notepad++ oder Visual Studio Code als Editor auf dem Server

Damit die WID Laufwerk D: verwendet, sind die folgenden Schritte notwendig.

Start der Windows Internal Database über die Services oder PowerShell

image

image

# Starten der WID
Start-Service -Name 'MSSQL$MICROSOFT##WID'
# Ändern des StartupTypes auf Automatic (delayed)
Set-Service -Name 'MSSQL$MICROSOFT##WID' -StartupType Automatic

Nun ist es möglich, mit dem folgenden String eine Verbindung zur WID über das SQL Server Management Studio (SSMS) herzustellen.

np:\\.\pipe\MICROSOFT##WID\tsql\query

Das SSMS muss dazu mit administrativen Rechten (rechte Maustaste Run as Administrator) gestartet worden sein.

image

Der weitere Ablauf ergibt sich aus den folgenden Schritten.

  • Stoppen der WID, durch das SSMS, PowerShell oder auch den Services Manager
  • Anlegen des Data und Log Verzeichnisses auf Laufwerk D (als Administrator)

image

  • Verschieben des Inhalts von C:\Windows\wid\data und C:\Windows\wid\log nach Laufwerk D:

image

Verschieben von Data und Log auf Laufwerk D
move C:\Windows\wid\data\* 'D:\Microsoft SQL Server\WID\Data\'
move C:\Windows\wid\log\* 'D:\Microsoft SQL Server\WID\Log\'
  • Ändern der folgenden drei Einträge in der Registry, für die Lokation der master. mdf, master.ldf und error.log Dateien

image

  • Der neue Pfad geht auf Laufwerk D mit den Unterverzeichnissen

image

  • Danach folgt die Berechtigung des WID Service Accounts auf die Verzeichnisse auf Laufwerk D … der Einfachheit nehme ich hier immer das WID-Verzeichnis selbst.

image

NT SERVICE\MSSQL$MICROSOFT##WID 
  • Danach kann die WID gestartet werden und die Verbindung über das SSMS klappt auch ohne Probleme.

image

Die Installation des WSUS erfolgt über den Post-Configuration Task oder kann über den folgenden Aufruf erfolgen.

# wsusutil.exe liegt im Verzeichnis C:\Program Files\Update Services\Tools
.\wsusutil.exe postinstall SQL_INSTANCE_NAME="LOCALHOST" CONTENT_DIR=D:\WSUS

image

Enjoy it, b!

Microsoft SQL Server Login Probleme

Auf einem SQL Server 2012 Express (der eigentlich nur die Datenbank für den WSUS) bereit stellt, kam es zu dem Problem das ich mich nicht mehr über das SQL Server Management Studio anmelden konnte, oder das zwar die Anmeldung klappte aber der Zugriff auf die WSUS Datenbank (SUSDB) mit fehlenden Rechten verweigert wurde. Den SA konnte ich dazu auch nicht mehr aktivieren, obwohl ich Domain-Admin war.

Die Ursache des Problems

Das Problem lag darin, das während des Setups der Benutzer als Administrator zum SQL-Server hinzugefügt wurde. Irgendwann, wurde aber genau dieser Administrator gelöscht und wieder neu angelegt. Damit war der Zugriff auf den SQL Server nicht mehr möglich.

image

How to fix this

Die Lösung ist, wenn man sie kennt, relativ einfach. In einem ersten Schritt müssen wir herausfinden wie die Instanz des SQL Servers heißt. Das geht am einfachsten mit net start, im Anschluss wird die Instanz mit net stop gestoppt. Am einfachsten ist es alle Schritte in einer PowerShell oder Command Line mit erhöhten Rechten aus zu führen. Die Abfrage an sich geht zwar auch ohne, aber zum Stopp sind diese Rechte notwendig.

net start
...
SQL Server (MSSQLSERVER)
...

Stopp der SQL Server Instanz.

net stop "SQL Server (MSSQLSERVER)"

Der ganze Ablauf sieht dann wie folgt aus.

image

Sollte bei der Abfrage der SQL Server Agent auftauchen, so muss dieser ebenfalls gestoppt und deaktiviert werden! Wie hier, im Bild oben zu sehen ist, war das aber nicht notwendig.

Nun wird die SQL Server Instanz mit dem optionalen Schalter /m im Single-User Mode gestartet. Nun kann lediglich EIN einziger Benutzer die Verbindung zur Datenbank aufbauen (was auch die Grund ist den Agenten zu stoppen, startet dieser nämlich wieder zusammen mit dem SQL Server, dann ist die eine Verbindung belegt). Der Start im Singe-User Mode ermöglicht einem Mitglied der lokalen Administratoren die Verbindung als SYSADMIN auf zu bauen, damit haben wir die notwendigen Rechte um unser Problem zu fixen.

Der Start der SQL Server Instanz funktioniert analog zum Stopp, nur das dazu der Parameter /m verwendet wird.

net start "SQL Server (MSSQLSERVER)" /m

image

Nachdem die SQL Server Instanz erfolgreich gestartet wurde, kann eine Verbindung mit dem SQL Server Management Studio hergestellt werden und da wir mit SYSADMIN Rechten unterwegs sind, das Problem mit dem Login korrigiert werden.

Das SQL Server Management Studio starte ich in diesem Fall ebenfalls mit erhöhten Rechten (rechte Maustaste, …).

Nun wird unter Security/Logins der Benutzer (DOMAIN\USER) aus dem AD hinzugefügt und mit den folgenden Server Rollen ausgestattet:

  • public (Default)
  • sysadmin

image

Zusätzlich habe ich auch den SA mit einem schweren Passwort versehen und aktiviert.

Nach dem beenden des SQL Server Management Studios, muss die SQL Server Instanz gestoppt und wieder normal gestartet werden.

net stop "SQL Server (MSSQLSERVER)"
...
net start "SQL Server (MSSQLSERVER)"

image

Nach dem Neustart fehlte lediglich die Zuweisung des wieder angelegten Benutzers als DBO zur Datenbank. Der nun folgende Befehl wird im SQL Server Management Studio ausgeführt und ordnet den Benutzer zu.

ALTER AUTHORIZATION ON DATABASE::SUSDB TO [DOMAIN\USER];

image

Nun ist der volle Zugriff auf die SUSDB wieder vorhanden und ich kann sie endlich kleiner machen.

Enjoy it, b!

Goodmorning WSUS

Hier mal wieder ein Beitrag zu meiner Lieblingstechnologie, dem WSUS.

Prinzipiell ermöglicht der WSUS die Nutzung einer Vielzahl von SQL Server Editionen, besonders häufig treffe ich auf die Installation des WSUS in Verbindung mit der SQL Server Express Edition. Diese Edition verwende ich (nicht zuletzt, weil sie nichts kostet) ebenfalls sehr gerne auch für andere Anwendungen. Allerdings muss man hier auf eine Kleinigkeit achten, eine Datenbank darf nicht größer als 10GB werden und damit kommen wir wieder zum WSUS. Die 10GB Grenze sprengt der WSUS bei einer Reihe meiner Installationen, bzw. bewegt sich knapp darüber. Nun stellt sich die Frage: Wie bekomme ich die WSUS Datenbank (die übrigens immer noch SUSDB heißt) wieder klein, also unter die 10GB Grenze.

Die Überschreitung dieser, kündigt sich übrigens auch im Application Eventlog des Servers an.

image

Ist die WSUS Datenbank größer als 10GB geworden, haben wir zwei Möglichkeiten. Wechsel der Datenbank Editon im Hintergrund (SQL Server Standard zum Beispiel) was aber mit Kosten verbunden ist oder versuchen die WSUS Datenbank zu verkleinern.

Verkleinern der WSUS Datenbank

Dazu sind drei Schritte (mit möglichen Wiederholungen) notwendig.

  1. Entfernen von nicht mehr notwendigen Updates, etc.
  2. Ein auf T-SQL basierender WSUS Maintenance Task, https://gallery.technet.microsoft.com/scriptcenter/6f8cde49-5c52-4abd-9820-f1d270ddea61
  3. Abschließender „Shrink“ der WSUS Datenbank

Klingt eigentlich ganz einfach und das ist es eigentlich auch Winking smile 

Schritt 1 – Entfernen von nicht mehr notwendigen Updates …

Für das Entfernen von nicht mehr notwendigen Updates hat Microsoft den Server Cleanup Wizard in den WSUS integriert.

image

Der funktioniert auch gelegentlich, insofern man nicht gleiche alle Optionen auf einmal wählt. In letzter Zeit hatte ich häufig den Fall, dass sich der WSUS im Hintergrund beendet oder der Wizard selbst die gewählten Aufgaben nicht vollständig zu Ende bringen konnte. Einfacher und deshalb von mir bevorzugt finde ich das Durchführen der Bereinigung mit PowerShell.

Invoke-WsusServerCleanup -DeclineSupersededUpdates -DeclineExpiredUpdates -CleanupObsoleteComputers -CleanupObsoleteUpdates

Der Aufruf läuft zwar auch nicht auf Anhieb durch, kann aber im Falle einer Terminierung problemlos nochmals gestartet werden. Ich musste das auf einem Server 9x wiederholen, wichtig dabei ist das eine Bereinigung stattfinden nur leider nicht fertig wird. Ein wiederholter Aufruf (Pfeil Oben-Taste in der PowerShell Konsole) macht da weiter wo der Abbruch stattfand und kommt nach einigen Durchläufen zu einem positiven Ergebnis.

Der folgende Screenshot zeigt die letzten beiden Timeouts des Befehls (#7 und #8) und letztendlich die erfolgreiche Bereinigung (Obsolete Updates Deleted: 103).

image

Im nächsten Schritt müssen wir die SQL Datenbank des WSUS (SUSDB) einem Maintenance Task unterziehen.

Schritt 2 – WSUS Database Maintenance Task

Dafür verwenden wir in Script aus der Technet Gallery …

/******************************************************************************
This sample T-SQL script performs basic maintenance tasks on SUSDB
1. Identifies indexes that are fragmented and defragments them. For certain
   tables, a fill-factor is set in order to improve insert performance.
   Based on MSDN sample at http://msdn2.microsoft.com/en-us/library/ms188917.aspx
   and tailored for SUSDB requirements
2. Updates potentially out-of-date table statistics.
******************************************************************************/

USE SUSDB;
GO
SET NOCOUNT ON;

-- Rebuild or reorganize indexes based on their fragmentation levels
DECLARE @work_to_do TABLE (
    objectid int
    , indexid int
    , pagedensity float
    , fragmentation float
    , numrows int
)

DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @schemaname nvarchar(130); 
DECLARE @objectname nvarchar(130); 
DECLARE @indexname nvarchar(130); 
DECLARE @numrows int
DECLARE @density float;
DECLARE @fragmentation float;
DECLARE @command nvarchar(4000); 
DECLARE @fillfactorset bit
DECLARE @numpages int

-- Select indexes that need to be defragmented based on the following
-- * Page density is low
-- * External fragmentation is high in relation to index size
PRINT 'Estimating fragmentation: Begin. ' + convert(nvarchar, getdate(), 121) 
INSERT @work_to_do
SELECT
    f.object_id
    , index_id
    , avg_page_space_used_in_percent
    , avg_fragmentation_in_percent
    , record_count
FROM 
    sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'SAMPLED') AS f
WHERE
    (f.avg_page_space_used_in_percent < 85.0 and f.avg_page_space_used_in_percent/100.0 * page_count < page_count - 1)
    or (f.page_count > 50 and f.avg_fragmentation_in_percent > 15.0)
    or (f.page_count > 10 and f.avg_fragmentation_in_percent > 80.0)

PRINT 'Number of indexes to rebuild: ' + cast(@@ROWCOUNT as nvarchar(20))

PRINT 'Estimating fragmentation: End. ' + convert(nvarchar, getdate(), 121)

SELECT @numpages = sum(ps.used_page_count)
FROM
    @work_to_do AS fi
    INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id
    INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id

-- Declare the cursor for the list of indexes to be processed.
DECLARE curIndexes CURSOR FOR SELECT * FROM @work_to_do

-- Open the cursor.
OPEN curIndexes

-- Loop through the indexes
WHILE (1=1)
BEGIN
    FETCH NEXT FROM curIndexes
    INTO @objectid, @indexid, @density, @fragmentation, @numrows;
    IF @@FETCH_STATUS < 0 BREAK;

    SELECT 
        @objectname = QUOTENAME(o.name)
        , @schemaname = QUOTENAME(s.name)
    FROM 
        sys.objects AS o
        INNER JOIN sys.schemas as s ON s.schema_id = o.schema_id
    WHERE 
        o.object_id = @objectid;

    SELECT 
        @indexname = QUOTENAME(name)
        , @fillfactorset = CASE fill_factor WHEN 0 THEN 0 ELSE 1 END
    FROM 
        sys.indexes
    WHERE
        object_id = @objectid AND index_id = @indexid;

    IF ((@density BETWEEN 75.0 AND 85.0) AND @fillfactorset = 1) OR (@fragmentation < 30.0)
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';
    ELSE IF @numrows >= 5000 AND @fillfactorset = 0
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD WITH (FILLFACTOR = 90)';
    ELSE
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';
    PRINT convert(nvarchar, getdate(), 121) + N' Executing: ' + @command;
    EXEC (@command);
    PRINT convert(nvarchar, getdate(), 121) + N' Done.';
END

-- Close and deallocate the cursor.
CLOSE curIndexes;
DEALLOCATE curIndexes;


IF EXISTS (SELECT * FROM @work_to_do)
BEGIN
    PRINT 'Estimated number of pages in fragmented indexes: ' + cast(@numpages as nvarchar(20))
    SELECT @numpages = @numpages - sum(ps.used_page_count)
    FROM
        @work_to_do AS fi
        INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id
        INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id

    PRINT 'Estimated number of pages freed: ' + cast(@numpages as nvarchar(20))
END
GO


--Update all statistics
PRINT 'Updating all statistics.' + convert(nvarchar, getdate(), 121) 
EXEC sp_updatestats
PRINT 'Done updating statistics.' + convert(nvarchar, getdate(), 121) 
GO

… das über das SQL Server Management Studio ausgeführt wird.

image

Einfach reinkopieren und (New Query) und mit Execute ausführen, dass Script selektiert die SUSDB gleich zu Anfang und beginnt die Indizes neu zu organisieren.

Nun kann die SUSDB verkleinert (Shrink) werden.

Schritt 3 – Verkleinern (Shrink) der SUSDB

Dazu wählen wir im Object Explorer des Microsoft SQL Server Management Studios die SUSDB aus.

image

Danach mit der rechten Maustaste Tasks / Shrink / Database und klicken hier auf OK.

Wie im Screenshot zu sehen ist, hat die Datenbank auf einmal 64% freien Platz … was doch ganz ordentlich ist.

image

Wie alles beim WSUS dauert das verkleinern seine Zeit, danach haben wir aber das Problem für die nächste Zeit behoben.

Vorher:

08.05.2018  05:56    10.652.549.120 SUSDB.mdf

Nachher:

08.05.2018  06:16     3.385.720.832 SUSDB.mdf

Enjoy it, b!

Application ESENT 490 Error, SQL Server 2016

Auf einem Windows Server Essentials mit installierten SQL Server 2016 Express hatte ich im Eventlog den folgenden Fehler gefunden.

image

svchost (7204) An attempt to open the file "C:\Windows\system32\LogFiles\Sum\Api.log" for read / write access failed with system error 5 (0x00000005): "Access is denied. ".  The open file operation will fail with error -1032 (0xfffffbf8).

Der Microsoft KB-Artikel 2811556 beschreibt hier als Lösung, dass Hinzufügen des SQL Server Service Accounts (Dienstkonto unter dem der SQL Server läuft) mit entsprechenden Berechtigungen auf das Verzeichnis Sum.

"C:\Windows\System32\LogFiles\Sum"

Der Service Account ist in diesem Fall ein sogenannter Virtual Account (NT Service\MSSQLSERVER) welcher nicht im Active Directory, sondern in der lokalen Benutzer-Datenbank des Servers zu finden ist.

image

Um diesen Account hinzu fügen zu können, muss darauf geachtet werden, dass in der Location nicht die Domain, sondern der Name des Servers selbst ausgewählt wurde, dann kann im Feld weiter unten NT Service\MSSQLSERVER eingetragen werden, was automatisch in MSSQLSERVER expandiert wird.

image

Auf das Verzeichnis Sum habe ich dann Modify als Berechtigung vergeben und nach unten vererbt.

image

Im Anschluss war ein Start des SQL Servers ohne die Fehlermeldung möglich.

An dieser Stelle möchte ich noch Euch allen ein Gutes Neues Jahr wünschen!

Enjoy it, b!