our ceux qui ont déjà tenté l’expérience, la migration d’un plan de maintenance sous SQL Server réserve quelques surprises. En effet, la connexion locale associée au package n’est pas modifiable et il faut à posteriori créer une nouvelle connexion et modifier les tâches du plan en conséquence pour qu’elles prennent en compte la nouvelle connexion. Il va sans dire que cela n’est pas forcément pratique et bien souvent on préfère recréer le plan de maintenance sur le nouveau serveur soit "from scratch" soit avec des copier-coller. De la même manière si on veut changer le propriétaire d’un job lié à un plan de maintenance on se retrouve rapidement confronté à quelques difficultés. Le fait de changer le propriétaire d’un job est plutôt facile en soi mais si on modifie et revalide le plan de maintenance par la suite celle-ci écrase notre changement de propriétaire. L’astuce consiste à changer le propriétaire du package SSIS associé au plan de maintenance concerné. Voici une procédure qui vous permettra de changer rapidement ces 2 paramètres après migration.
Ce script a été testé sur SQL Server 2008 / 2008 R2 et 2012. Pour la version 2005, il faudra remplacer la table msdb.dbo.sysssispackages par msdb.dbo.sysdtspackages90. /!\ A vérifier sur cette version d’environ /!\ Si quelqu’un a le temps de tester et me donner un feedback je suis preneur
Les paramètres d’entrées sont les suivants :
- @change_type : Contrôle processus de modification du package SSIS associé au plan de maintenance. Les valeurs possibles sont OWNER (changement de propriétaire), CONNECTION (changement du nom de serveur dans la chaine de connexion) ou ALL (changement des 2 paramètres)
- @maintenance_plan : Nom du plan de maintenance concerné
- @oldersername : Nom du l’ancien serveur qui hébergeait le plan de maintenance
- @newservername : Nom du nouveau serveur qui héberge le plan de maintenance
- @newowner : Nom du nouveau propriétaire du package SSIS associé au plan de maintenance
[sourcecode language='sql' padlinenumbers='true'] SET NOCOUNT ON; DECLARE @change_type VARCHAR(10) = 'CONNECTION'; -- Type of change : CONNECTION / OWNER / ALL DECLARE @maintenance_plan SYSNAME = 'MaintenancePlan'; -- Name of the maintenance plan to apply changes DECLARE @oldservername SYSNAME = 'OLDERSERVERNAME'; -- Name of the old server that hosted the maintenance plan DECLARE @newservername SYSNAME = @@SERVERNAME; -- Name of the new server that hosts the maintenance plan DECLARE @newowner SYSNAME = 'LANGROUP\dbn'; -- Name of the new owner for the maintenance plan (ssis) DECLARE @oldowner SYSNAME; DECLARE @debug BIT = 0; -- ACTIVE DEBUG (=1) DECLARE @xml NVARCHAR(MAX); -- Verification of existing maintenance plan IF NOT EXISTS (SELECT * FROM msdb.dbo.sysssispackages WHERE name = @maintenance_plan) BEGIN RAISERROR('The maintenance plan %s doesnt exist', 16, 1, @maintenance_plan); RETURN; END -- Verification of the type of change IF @change_type NOT IN ('CONNECTION', 'OWNER', 'ALL') BEGIN RAISERROR('The @change_type parameter must equal to CONNECTION, OWNER OR ALL', 16, 1); RETURN; END -- Changing of the connection string value IF @change_type IN ('ALL', 'CONNECTION') BEGIN PRINT 'REPLACE OLD SERVER NAME ' + @oldservername + ' BY THE NEW SERVER NAME : ' + @newservername + ' INTO THE MAINTENANCE PLAN'; BEGIN TRY SELECT @xml = cast(cast(cast(packagedata as varbinary(max)) as xml) as nvarchar(max)) FROM msdb.dbo.sysssispackages WHERE name = @maintenance_plan; -- DEBUG IF @DEBUG = 1 SELECT CAST(@xml AS XML) AS before_change; -- Case when connection string use server parameter IF (@xml LIKE '%server=''' + @oldservername + '%') BEGIN PRINT '--> Maintenance Plan with server parameter'; SET @xml= replace(@xml,'server=''' + @oldservername + '','server=''' + @newservername + ''); END -- Case when connection string use Data source parameter IF (@xml LIKE '%Data Source=''' + @oldservername + '%') BEGIN PRINT '--> Maintenance Plan with Data Source parameter'; SET @xml= replace(@xml,'Data Source=''' + @oldservername + '','Data Source=''' + @newservername + ''); END PRINT 'Update maintenance plan done …'; -- DEBUG IF @DEBUG = 1 SELECT CAST(@xml AS XML) AS after_change; -- Validation of the xml document after replacing the connection string SELECT CAST(@xml AS XML); -- Update ssis package with new connection string UPDATE msdb.dbo.sysssispackages SET packagedata = CAST(@xml AS VARBINARY(MAX)) WHERE name = @maintenance_plan; END TRY BEGIN CATCH PRINT CHAR(13) + 'An error occured during the update of the maintenance plan : ' + CHAR(13) + 'Error : ' + CAST(ERROR_NUMBER() AS VARCHAR(4)) + ' Severity : ' + CAST(ERROR_SEVERITY() AS VARCHAR(4)) + ' State : ' + CAST(ERROR_STATE() AS VARCHAR(4)) + CHAR(13) + ERROR_MESSAGE() END CATCH; END; -- Changing of the owner of the maintenance plan IF @change_type IN ('ALL', 'OWNER') BEGIN IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = @newowner) BEGIN RAISERROR('The new owner %s of the maintenance plan doesnt exist on the SQL Server instance.', 16, 1, @newowner); RETURN; END SELECT @oldowner = sp.name FROM sys.server_principals AS sp INNER JOIN msdb.dbo.sysssispackages AS ssis ON sp.sid = ssis.ownersid WHERE ssis.name = @maintenance_plan; PRINT 'REPLACE OLD OWNER ' + COALESCE(@oldowner, 'UNKNOW ') + ' BY THE NEW OWNER : ' + @newowner; IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = @newowner) BEGIN RAISERROR('The new owner %s for the maintenance plan %s doesnt exist on the SQL Server instance.', 16, 1, @maintenance_plan, @newowner); RETURN; END -- Update owner of the SSIS package UPDATE msdb.dbo.sysssispackages SET ownersid = (SELECT [sid] FROM sys.server_principals WHERE name = @newowner) WHERE name = @maintenance_plan; PRINT 'Update owner of the maintenance plan done …'; -- Update owner of the corresponding SQL job WITH cte_owner_job AS ( SELECT ssis.name, j.owner_sid FROM msdb.dbo.sysssispackages AS ssis INNER JOIN msdb.dbo.sysmaintplan_subplans AS sp ON ssis.id = sp.plan_id INNER JOIN msdb.dbo.sysjobs AS j ON j.job_id = sp.job_id where ssis.name = @maintenance_plan ) UPDATE cte_owner_job SET owner_sid = (select [sid] from sys.server_principals WHERE name = @newowner); PRINT 'Update owner of the corresponding SQL Server jobs …'; END; [/sourcecode]
Bonne migration de plan de maintenance !!
David BARBARIN (Mikedavem)
MVP SQL Server
Merci David pour ce script très utile.
Juste une remarque dans mon cas pour un plan de maintenance créé avec SQL 2012, il n’y a pas de ‘ (apostrophe) autour du nom du serveur aussi j’ai du ajouter le code suivant:
— Case when connection string use Data source parameter without ‘
IF (@xml LIKE ‘%Data Source=’ + @oldservername + ‘%’)
BEGIN
PRINT ‘–> Maintenance Plan with Data Source parameter';
SET @xml= replace(@xml,’Data Source=’ + @oldservername + »,’Data Source=’ + @newservername + »);
END
Encore merci!
Merci à Christophe Laporte (http://conseilit.wordpress.com/) pour sa remarque concernant les différents paramètres que l’on peut avoir dans l’élément connectionstring (server ou data source). J’ai modifié le script en conséquence.