Schlagwort: Database

  • SharePoint – Tenant-OU wieder freigeben

    SharePoint 2016 hat (anders als SharePoint 2019) noch Multi-Tenancy-Unterstützung. Das heisst, man kann einige Service-Applikationen, wie z.B. den Managed Metadata Service oder den User Profile Service für verschiedene Tenants Partitionieren – im Prinzip das, was Microsoft auch in SharePoint Online macht, um verschiedenen Kunden einen eigenen Bereich in den Service-Applikationen zu geben.

    Beim erstellen eines Tenants, wird mit New-SPSiteSubscription so eine Partition für den Tenant registriert.

    Mann kann dann mit dieser Subscription z.B. den People Picker auf eine OU (Organizational Unit im Active Directory) einschränken:

    Set-SPSiteSubscriptionConfig -identity $siteSubscription -FeaturePack $defaultfeaturePackId -UserAccountDirectoryPath "OU=UserAccounts,DC=FABRIKAM,DC=COM"

    Beim Erstellen einer Site Collection für den Tenant wird diese Subscription auch mitgegeben:

    New-SPSite -Url https://fabrikam.sptest.local" -SiteSubscription $siteSubscription -HostHeaderWebApplication "https://root.sptest.local"

    Und mit folgendem Befehl Add-SPSiteSubscriptionProfileConfig wird eingestellt, dass für diese Subscription die AD-Benutzer mit der entsprechenden OU synchronisiert werden (für die User Profile Service Application).

    $upaProxy = Get-SPServiceApplicationProxy | where-object { $_.DisplayName -eq "MT User Profile Service Application" }
    Add-SPSiteSubscriptionProfileConfig -Identity $siteSubscription -SynchronizationOU "OU=UserAccounts,DC=FABRIKAM,DC=COM" -ProfileServiceApplicationProxy $upaProxy

    Wenn man zu einem späteren Zeitpunkt den Tenant löschen möchte, zum Beispiel weil beim Erstellungsprozess etwas schief gelaufen ist, dann muss man schlau vorgehen, damit die OU wiederverwendet werden kann. Eine OU kann nämlich nicht von mehr als einer Subscription verwendet werden.

    Mit folgenden Schritten (in der SharePoint Management Shell) kann man eine Subscription und die zugehörige Subscription-Profile-Config löschen. Achtung: es werden dabei alle Site Collections gelöscht, welche zur jeweiligen Subscription gehören!

    Zuerst holt man sich die jeweilige Subscription, welche gelöscht werden soll, zum Beispiel über den URL der Site:

    # Site holen
    $site = Get-SPSite "http://fabrikam.sptest.local"
    
    # subscription der Site holen
    $subscription = $site.SiteSubscription

    Dann muss man sich die User Profile Service Application holen (darauf achten, dass die richtige Multi-Tenancy-fähige Service-Applikation geholt wird, falls ihr mehere, z.B. auch eine normale, in der Farm habt).

    # Namen des UPA Proxys angeben
    $upaProxyName = "MT User Profile Service Application"
    
    # UPA Proxy holen
    $upaProxy = Get-SPServiceApplicationProxy | where-object { $_.DisplayName -eq $upaProxyName }

    Nun kann man als erstes die OU-Synchronisierung entfernen, es darf auf keinen Fall zuerst die Subscription direkt gelöscht werden, denn das wäre möglich und würde das ausführen dieses Befehls verunmöglichen, was dazu führt, dass man die OU nur noch über die manuelle Bearbeitung der Datenbank erledigen kann (was Microsoft nicht gerne hat):

    # UPA Subscription Eintrag entfernen (aus UPA Profile DB für Profile Sync.)
    Remove-SPSiteSubscriptionProfileConfig -Identity $subscription -ProfileServiceApplicationProxy $upaProxy
    

    Nun kann die Subscription gelöscht werden. Um Sicherzugehen, welche Sites betroffen sind, kann man zuerst $subscription.Sites aufrufen:

    # Site subscription und alle assozierten Sites löschen
    Remove-SPSiteSubscription -Identity $subscription

    Am Ende kann noch die Inhaltsdatenbank gelöscht werden, in welcher die Site Collection für den Tenant gespeichert war (sinnvoll falls man pro Tenant eine eigene Inhaltsdatenbank verwendet):

    # Zum Schluss die Inhaltsdatenbank entfernen. Auch hier sollte man zuerst prüfen, dass keine anderen Sites in der Inhaltsdatenbank sind! (Befehl geht auch, wennd die Site zuvor gelöscht wurde, das Objekt hat noch den Wert der Datenbank und den Datenbanknamen)
    $databaseName = $site.ContentDatabase.Name
    Remove-SPContentDatabase -Identity $databaseName

    Dies war der Weg um einen Tenant sauber zu löschen, so dass die OU die verwendet wurde, auch später wieder neu verwendet werden kann.

    Falls man diesen Weg nicht eingehalten hat und z.B. die Site-Subscription schon gelöscht hat, ohne zuerst Remove-SPSiteSubscriptionProfileConfig auszuführen, dann bleibt einem nur noch der Weg, die Subscription manuell aus der Datenbank zu entfernen, dies führt gemäss Microsoft zum Verlust der Garantie!

    Es handelt sich dabei um die Profile DB der User Profile Service Application, in welcher in diversen Tabellen die Einträge für unsere Subscription (Partition-ID) gelöscht werden müssen.

    Nachfolgend ein SQL-Script, mit welchem man dies machen könnte, Verwendung aber auf eigene Gefahr. Wichtig ist, dass ihr in der ersten Zeile den Wert der Variable SubscriptionId auf die entsprechende Subscription-ID setzt und danach natürlich [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa] mit der ensprechenden Datenbank und dem entsprechenden Schema für euren Fall:

    DECLARE @SubscriptionId AS Varchar(255) = '6d947c20-f876-4d4b-b680-1f0cd0a78c6f'
    
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ProfileSubtypeList WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].PersonalSite WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_Stats WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_OpList WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_List WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Orgle_ErrorMsg WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].InternalDetail WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].DataTypeList WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].DataServiceList WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].BucketInfo WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].MicrofeedPostDefinitions WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityTemplate WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityApplication WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityType WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ActivityApplication WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Profile_SearchStopwords WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Profile_SearchUserTable WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].OrganizationProfileValue WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].OrganizationProfile WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserProfileEventLog WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserProfileValue WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserProfile_Full WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].UserPrivacyPolicy WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ADImportConstantPropertyMapping WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ADImportPropertyMapping WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ProfileSubtypePropertyAttributes WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].ProfileTypePropertyAttributes WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].PropertyList WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].[Profile_Stats] WHERE PartitionID = @SubscriptionId
    Delete
      FROM [SharePoint_MT_User_Profile_Service_Application_ProfileDB].[upa].Tenants WHERE PartitionID = @SubscriptionId

    Es empfiehlt sich danach etwas zu warten, da diese Änderungen nicht sofort ziehen. Im Idealfall könnt ihr danach einen IISReset auf allen SharePoint-Servern durchführen und ich würde auch die Instanz auf dem Datenbankserver neu starten.

  • Eine „suspect“ Datenbank reparieren

    Es ist mir schon passiert, dass ich auf einmal keine SharePoint-Webseite meiner Virtual Machine mehr öffnen konnte. Auch die Central Administration funktionierte nicht mehr. Als Fehlermeldung erschien:

    „This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this server to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu…“

    Ein Ausführen des SharePoint Products Configuration Wizards war nicht möglich, der Wizard brach nach einigen Schritten ab, mit der Begründung, dass nicht auf die Configuration-Datenbank zugegriffen werden konnte.

    Ein Blick in das MSSQL Management Studio zeigte dann, dass die SharePoint-Config-Datenbank im Status suspect, also verdächtig war.

    Zum Glück gibt es einen Weg, die Datenbank wieder in einen gesunden Zustand zu bringen, oder zumindest es zu versuchen. Achtung: je nach Schweregrad der zu Grunde liegenden Störung kann es sein, dass bei diesem Vorgang Daten verloren gehen, da hier eine Reparatur der Datenbank mit „REPAIR_ALLOW_DATA_LOSS“ durchgeführt wird.

    Via MSSQL Management Studio auf den Datenbankserver verbinden und ein neues Query-Fenster öffnen, danach folgende Zeilen ausführen („DatabaseName“ durch den Namen der „suspect“ Datenbank ersetzen):

    EXEC sp_resetstatus [DatabaseName];
    ALTER DATABASE [DatabaseName] SET EMERGENCY
    DBCC checkdb([DatabaseName])
    ALTER DATABASE [DatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    DBCC CheckDB ([DatabaseName], REPAIR_ALLOW_DATA_LOSS)
    ALTER DATABASE [DatabaseName] SET MULTI_USER

    Je nach Grösse der Datenbank, Server-Leistung und Fehler-Anzahl kann der Vorgang zwischen wenigen Sekunden bis hin zu Stunden dauern. Bei mir brauchte es für eine 1 GB grosse Datenbank zum Beispiel ca. eine Minute. Im Ausgabefenster ist ersichtlich, was für Reparaturen vorgenommen wurden und ob diese zu Datenverlust führten.

    Nachdem die Operation beendet wurde, kann man versuchen wieder auf die Datenbank zuzugreifen. In meinem Fall konnte ich wieder auf die SharePoint-Central-Administration und die Web-Applications zugreifen.

  • Microsoft SQL Server Management Studio – verbleibende Datenbank-Restore-Dauer anzeigen

    Microsoft SQL Server Management Studio – verbleibende Datenbank-Restore-Dauer anzeigen

    Vielleicht habt ihr auch schon mal in einem Microsoft SQL Server einen Restore einer Datenbank durchgeführt und wolltet wissen, wie weit der Restore nach einigen Minuten/Stunden schon gekommen ist und wann der Restore ungefähr beendet sein wird.

    Wird der Restore via „Management Studio“-GUI durchgeührt (Datenbank-Kontextmenü -> Tasks -> Restore), dann habt ihr im Restore-Dialog zumindest eine ungefähre Prozent-Anzeige. In der 2012er-Version wird diese oben rechts angezeigt:

    Die Prozent-Anzeige erscheint aber erst nach einem Weilchen und wenn man den Restore via SQL-Skript gestartet hat und dabei „STATS“ nicht (oder mit einem ungünstigen Wert) verwendet hat, weiss man auch nicht bei wieviel Prozent der Restore aktuell steht und wie lange er noch dauert. Häufig bleibt die Prozentzahl auch lange unverändert und man ist sich nicht sicher, ob der Restore noch läuft oder sich aufgehängt hat.

    Zum Glück gibt es jedoch eine Möglichkeit mit einem SQL-Befehl den aktuellen Fortschritt und die geschätzte Endzeit zu erhalten – egal ob  der Backup-Job via GUI, Skript oder sogar von einer anderen Maschine gestartet wurde. Voraussetzung ist ein MSSQL Server der Dynamic Management Views (DMVs) unterstützt, also ab MSSQL 2005. Ist das gegeben kann man folgenden Befehl als Query absetzen (es muss keine Datenbank dazu vorselektiert werden):

    SELECT session_id as SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time
    FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a
    WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE')

    Das Resultat sieht dann zum Beispiel wie folgt aus (unterer Bereich, Spalten percent_complete und estimated_completion_time):

    Im Beispiel sieht man also, dass bereits 96.16975 % des Restores durchlaufen ist und der Restore um 12:38 Uhr, des 7. Dezember 2016, fertig sein sollte – nach ungefähr 19 Stunden Laufzeit. Praktisch oder?

    Gefunden auf: https://www.mssqltips.com/sqlservertip/2343/how-to-monitor-backup-and-restore-progress-in-sql-server/