Fallstricke bei der Migration von Report Server Datenbanken

Kürzlich habe ich eine Report Server Datenbank auf einen anderen Server mit SQL Server 2017 verschoben, der Report Server Service sollte danach die verschobene Datenbank verwenden. Das ging auch problemlos, aber leider konnten keine Abonnements angelegt werden.

Migrieren einer Report Server Datenbank

Das ist eigentlich kein großes Thema und beinhaltet diese Schritte, wobei ich die bestehende Installation der Reporting Services weiter verwendet habe, nur die Datenbank wurde umgezogen:

  • Sichern des Encryption Keys auf der alten Installation
  • Beenden der Reporting Services auf der alten Installation
  • Sichern der beiden Report Server Datenbanken: ReportServer und ReportServerTempDB auf der alten Instanz
  • Abhängen der beiden Report Server Datenbanken: ReportServer und ReportServerTempDB auf der alten Instanz
  • Wiederherstellen der beiden Report Server Datenbanken: ReportServer und ReportServerTempDB auf der neuen Instanz
  • Starten der Reporting Services (ggf. auf der neuen Installation)
  • Ändern der Datenbank-Verbindung auf die neuen Datenbanken
  • Der Neustart der Reporting Services erfolgt automatisch und dabei werden auch (normalerweise) alle Jobs angelegt, die für Abonnements benötigt werden
  • Wiederherstellen des vorher gesicherten Encryption Keys von der alten Installation
  • Sichern des Encryption Keys auf der neuen Installation, damit dieser in der File-Sicherung enthalten ist und ggf. wieder verwendet werden kann

Einrichten von Abonnements schlägt fehl

Wenn man die Schritte oben durchgeführt hat, dann läuft zwar der Report Server, aber beim Anlegen neuer Abonnements bekommt man einen Fehler. Das kann man auch schon vorab sehen, wenn für die alten Abonnements keine Jobs im SQL Server Agent angelegt wurden.

EXECUTE permission denied on object 'xp_sqlagent_notify', database 'mssqlsystemresource', schema 'sys'.

Diese Meldung kann man dann im Log des Report Servers sehen, im Browser sieht man allerdings:

Fehler in der Berichtsserver-Datenbank. Dies kann auf einen Verbindungsfehler, ein Timeout oder wenig Speicherplatz innerhalb der Datenbank zurückzuführen sein.

Diese Meldung ist allerdings wenig hilfreich.
Woran liegt es jetzt, dass die EXCUTE Berechtigung fehlt? Wer braucht die denn?

Die RSExecRole

In den beiden Datenbanken master und msdb gibt es die Rolle RSExecRole. Mitglied ist der Account, unter dem die Reporting Services laufen. Als erstes müssen wir also schauen, ob diese Rollen fehlen und sie dann ggf. anlegen.

USE MASTER
GO
CREATE ROLE RSExecRole;
GO
USE msdb
GO
CREATE ROLE RSExecRole;
GO

Danach können wir die notwendigen Berechtigungen an diese beiden Rollen vergeben:

USE MASTER
GO
GRANT EXECUTE ON MASTER.dbo.xp_sqlagent_notify TO RSExecRole;
GRANT EXECUTE ON MASTER.dbo.xp_sqlagent_enum_jobs TO RSExecRole;
GRANT EXECUTE ON MASTER.dbo.xp_sqlagent_is_starting TO RSExecRole;
GO

USE msdb
GO

-- Permissions for SQL Agent SP's
GRANT EXECUTE ON msdb.dbo.sp_help_category TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_add_category TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_add_job TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_add_jobserver TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_add_jobstep TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_add_jobschedule TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_help_job TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_delete_job TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_help_jobschedule TO RSExecRole;
GRANT EXECUTE ON msdb.dbo.sp_verify_job_identifiers TO RSExecRole;
GRANT SELECT ON msdb.dbo.sysjobs TO RSExecRole;
GRANT SELECT ON msdb.dbo.syscategories TO RSExecRole;

Danach müssen wir noch in beiden Datenbanken den Account aufnehmen, unter dem der Report Server Service läuft. In der msdb benötigt das Konto zusätzlich die Rechte eigene Jobs zu verwalten. Hier reicht also die Zugehörigkeit zur Rolle SQLAgentUserRole.

USE MASTER
GO
ALTER ROLE RSExecRole ADD MEMBER [<domain>\<SSRS-account>];
GO
USE msdb
GO
ALTER ROLE RSExecRole ADD MEMBER [<domain>\<SSRS-account>];
ALTER ROLE SQLAgentUserRole ADD MEMBER [<domain>\<SSRS-account>];
GO

Das komplette Skript gibt es hier auch zum Download:

  r01_rsexecrole.sql