Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment déplacer des fichiers de données dans SQL Server - Partie 1

Présentation

Il existe un certain nombre de situations qui justifieraient le déplacement de fichiers de base de données ou de fichiers journaux de transactions d'un volume à un autre sur le même serveur. Ceux-ci peuvent inclure :

  1. La nécessité de formater le volume en supposant qu'il n'a pas été correctement formaté lors de l'installation de SQL Server . N'oubliez pas que lors de l'installation de SQL Server, il est recommandé d'utiliser une taille d'unité d'allocation de 64 Ko pour formater les volumes. Si cela n'est pas fait au moment de l'installation et doit être fait plus tard, il faudra évidemment conserver une sauvegarde de la première base de données ou créer un nouveau volume correctement formaté et déplacer la base de données vers ce nouveau volume.
  2. La nécessité d'utiliser un nouveau volume en supposant que les limites ont été atteintes pour le stockage sous-jacent . Un bon exemple serait la limite de 2 To d'un magasin de données VMware. C'est le cas depuis VSphere 5.0. Les versions supérieures de VSphere ont des limites beaucoup plus élevées.
  3. La nécessité d'améliorer les performances en gérant les E/S . Une autre raison pour laquelle vous voudrez peut-être déplacer des fichiers de données est la performance. Il y a des cas où une base de données est créée avec plusieurs fichiers de données tous assis sur un seul disque jusqu'à ce qu'il devienne évident, à mesure que la base de données se développe, que vous avez créé une "région chaude" dans la couche de stockage. Une solution serait de créer de nouveaux fichiers de données et de reconstruire des index clusterisés, une autre serait de déplacer des fichiers de données.

Scénario 1 :Déplacement des bases de données utilisateur

Les étapes impliquées dans le déplacement d'une base de données d'utilisateurs impliquent les éléments suivants :

  1. Mettez la base de données hors ligne
  2. Mettre à jour le catalogue système avec le nouvel emplacement
  3. Copiez physiquement le fichier de données vers le nouvel emplacement
  4. Mettez la base de données en ligne

Le Listing 1 montre les commandes exécutées pour réaliser ces étapes.

Liste 1 Déplacement de fichiers de données

-- 1. Run the following statement to check the current location of files.
SELECT name, physical_name AS CurrentLocation, state_desc FROM sys.master_files WHERE database_id = DB_ID(N'BranchDB');
-- 2. Take the database offline.
ALTER DATABASE BranchDB SET OFFLINE;
-- 3. Move the file or files to the new location (at OS level).
-- 4. For each file moved, run the following statement.
ALTER DATABASE BranchDB MODIFY FILE ( NAME = WWI_UserData, FILENAME = 'N:\MSSQL\Data\WWI_UserDataNew.ndf' );
-- 5. Run the following statement.
ALTER DATABASE BranchDB SET ONLINE;
-- 6. Verify the file change by running the following query.
SELECT name, physical_name AS CurrentLocation, state_desc FROM sys.master_files WHERE database_id = DB_ID(N'BranchDB');

Il est important de noter que lors de la mise hors ligne d'une base de données, le nombre de sessions actives peut retarder le processus. Planifier un temps d'arrêt pour effectuer cette tâche serait une bonne idée. Pendant un tel temps d'arrêt, le propriétaire de l'application doit arrêter la connexion des services d'application à la base de données avant que l'administrateur de base de données ne tente de mettre la base de données hors ligne. Il y a des cas où il n'est pas si pratique de mettre la base de données hors ligne, alors l'arrêt de l'instance serait la meilleure option. Dans un tel cas, l'approche serait légèrement différente :

  1. Mettre à jour le catalogue système avec le nouvel emplacement
  2. Arrêter l'instance
  3. Copiez physiquement le fichier de données souhaité vers le nouvel emplacement
  4. Démarrer l'instance

Dans les deux approches, le concept est le même :il s'agit de mettre à jour le catalogue système dans la base de données principale, puis de déplacer physiquement le fichier de données souhaité. Dans les deux cas, le fichier de données doit être proprement fermé. Jetons un coup d'œil aux étapes impliquées dans la première approche.

Fig. 1 Vérifier l'emplacement des fichiers de données

La première étape serait de vérifier l'état de la chose pour commencer. Ensuite, passez à la mise hors ligne de la base de données et modifiez le catalogue système.

Fig. 2 Mettre la base de données hors ligne et modifier le catalogue

Comme le montre la figure 3, une fois que nous avons mis à jour le catalogue, l'interrogation de sys.master_files nous indique le nouvel emplacement dans lequel la base de données principale s'attend à ce que le fichier de données se trouve, que nous ayons physiquement déplacé le fichier ou non. Dans la figure 4, nous voyons également qu'il n'est pas possible de mettre la base de données en ligne sans d'abord déplacer physiquement le fichier vers le nouvel emplacement (et renommer le fichier pour qu'il corresponde au nouveau nom spécifié dans le catalogue).

Fig. 3 Nouveaux emplacements de fichiers

Fig. 4 Fichier manquant

Nous tenons également à souligner qu'une fois que nous avons copié le fichier, nous perdons les autorisations précédentes sur le fichier et SQL Server ne pourra pas ouvrir le fichier lorsque nous essaierons de mettre la base de données en ligne. Nous devons modifier les autorisations du fichier et ajouter accorder au compte NT SERVICE\MSSQLSERVER les autorisations complètes sur le fichier.

Fig. 5 Copiez le fichier de données

Fig. 6 Autorisations à destination

Fig. 7a Autorisations à la source

Fig. 7b Autorisations à la source

Si nous devions tenter de remettre la base de données en ligne avec ces autorisations manquantes, nous obtiendrions une erreur 0x5 (Accès refusé). Si nous devions faire quelque chose comme déplacer le fichier de données à l'aide d'un travail d'agent, nous constatons que le compte SQL Server Agent acquiert la propriété du fichier et nous ne pouvons apporter la base de données que parce que le compte SQL Server Agent est le même que le compte SQL Server.

Fig. 8 Accès refusé sur le nouveau fichier de données

En supposant que vous essayiez de mettre la base de données en ligne à l'aide de l'interface graphique SSMS, vous verriez ces erreurs dans l'Observateur d'événements ainsi que dans le journal des erreurs SQL Server si vous regardez attentivement. De plus, si vous utilisiez la deuxième approche (redémarrer l'intégralité de l'instance), vous observeriez que la base de données serait bloquée à l'étape de récupération. L'examen du journal des erreurs vous dira ce qui se passe réellement.

Liste 2 Déplacer des fichiers de données à l'aide d'un travail d'agent

/* ==Scripting Parameters==
Source Server Version : SQL Server 2017 (14.0.3023) Source Database Engine Edition : Microsoft SQL Server Standard Edition Source Database Engine Type : Standalone SQL Server
Target Server Version : SQL Server 2017 Target Database Engine Edition : Microsoft SQL Server Standard Edition Target Database Engine Type : Standalone SQL Server */
USE [msdb]
GO
/****** Object: Job [MoveDataFile] Script Date: 7/12/2018 12:33:55 AM ******/ BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT
	@ReturnCode = 0 /****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 7/12/2018 12:33:56 AM ******/
IF NOT EXISTS (SELECT
			name
		FROM msdb.dbo.syscategories
		WHERE name = N'[Uncategorized (Local)]'
		AND category_class = 1)
BEGIN
	EXEC @ReturnCode = msdb.dbo.sp_add_category @class = N'JOB'
											   ,@type = N'LOCAL'
											   ,@name = N'[Uncategorized (Local)]'
	IF (@@error <> 0
		OR @ReturnCode <> 0)
		GOTO QuitWithRollback
END
DECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name = N'MoveDataFile'
									  ,@enabled = 1
									  ,@notify_level_eventlog = 0
									  ,@notify_level_email = 0
									  ,@notify_level_netsend = 0
									  ,@notify_level_page = 0
									  ,@delete_level = 0
									  ,@description = N'No description available.'
									  ,@category_name = N'[Uncategorized (Local)]'
									  ,@owner_login_name = N'sa'
									  ,@job_id = @jobId OUTPUT
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback /****** Object: Step [MoveDataFile] Script Date: 7/12/2018 12:33:56 AM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @jobId
										  ,@step_name = N'MoveDataFile'
										  ,@step_id = 1
										  ,@cmdexec_success_code = 0
										  ,@on_success_action = 1
										  ,@on_success_step_id = 0
										  ,@on_fail_action = 2
										  ,@on_fail_step_id = 0
										  ,@retry_attempts = 0
										  ,@retry_interval = 0
										  ,@os_run_priority = 0
										  ,@subsystem = N'PowerShell'
										  ,@command = N'Copy-Item -Path M:\MSSQL\Data\WWI_UserData1.ndf N:\MSSQL\Data\WWI_UserData1.ndf'
										  ,@database_name = N'master'
										  ,@flags = 0
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId
										 ,@start_step_id = 1
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId
											,@server_name = N'(local)'
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@trancount > 0)
	ROLLBACK TRANSACTION
EndSave:
GO

Fig. 9 Autorisations sur le fichier de données lors de l'utilisation d'un travail d'agent

Fig. 10 Base de données en ligne

Automatisation du processus

Juste pour le plaisir, nous pouvons décider d'utiliser SQL Server Agent Job pour l'ensemble du processus. Nous configurons une étape de travail pour chaque étape de notre processus. Cela peut être utile si vous voulez être un DBA superstar et programmer une telle migration pendant la nuit pendant que vous rentrez chez vous et que vous vous détendez avec votre famille. Vous voudriez certainement vous assurer de configurer une notification pour qu'elle se déclenche lorsque le travail réussit afin d'être sûr qu'il sera effectivement effectué pendant votre absence.

Liste 3 Exécution de la tâche à l'aide d'un travail d'agent

/* ==Scripting Parameters==
Source Server Version : SQL Server 2017 (14.0.3023) Source Database Engine Edition : Microsoft SQL Server Standard Edition Source Database Engine Type : Standalone SQL Server
Target Server Version : SQL Server 2017 Target Database Engine Edition : Microsoft SQL Server Standard Edition Target Database Engine Type : Standalone SQL Server */
USE [msdb]
GO
/****** Object: Job [MoveDataFile] Script Date: 7/12/2018 12:46:47 AM ******/ BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT
	@ReturnCode = 0 /****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 7/12/2018 12:46:47 AM ******/
IF NOT EXISTS (SELECT
			name
		FROM msdb.dbo.syscategories
		WHERE name = N'[Uncategorized (Local)]'
		AND category_class = 1)
BEGIN
	EXEC @ReturnCode = msdb.dbo.sp_add_category @class = N'JOB'
											   ,@type = N'LOCAL'
											   ,@name = N'[Uncategorized (Local)]'
	IF (@@error <> 0
		OR @ReturnCode <> 0)
		GOTO QuitWithRollback
END
DECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name = N'MoveDataFile'
									  ,@enabled = 1
									  ,@notify_level_eventlog = 0
									  ,@notify_level_email = 3
									  ,@notify_level_netsend = 0
									  ,@notify_level_page = 0
									  ,@delete_level = 0
									  ,@description = N'No description available.'
									  ,@category_name = N'[Uncategorized (Local)]'
									  ,@owner_login_name = N'sa'
									  ,@notify_email_operator_name = N'DBA'
									  ,@job_id = @jobId OUTPUT
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
/****** Object: Step [Set Database Offline] Script Date: 7/12/2018 12:46:47 AM ******/ EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @jobId
																																 ,@step_name = N'Set Database Offline'
																																 ,@step_id = 1
																																 ,@cmdexec_success_code = 0
																																 ,@on_success_action = 3
																																 ,@on_success_step_id = 0
																																 ,@on_fail_action = 2
																																 ,@on_fail_step_id = 0
																																 ,@retry_attempts = 0
																																 ,@retry_interval = 0
																																 ,@os_run_priority = 0
																																 ,@subsystem = N'TSQL'
																																 ,@command = N'ALTER DATABASE BranchDB SET OFFLINE;'
																																 ,@database_name = N'master'
																																 ,@flags = 0
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback /****** Object: Step [MoveDataFile] Script Date: 7/12/2018 12:46:47 AM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @jobId
										  ,@step_name = N'MoveDataFile'
										  ,@step_id = 2
										  ,@cmdexec_success_code = 0
										  ,@on_success_action = 3
										  ,@on_success_step_id = 0
										  ,@on_fail_action = 2
										  ,@on_fail_step_id = 0
										  ,@retry_attempts = 0
										  ,@retry_interval = 0
										  ,@os_run_priority = 0
										  ,@subsystem = N'PowerShell'
										  ,@command = N'Copy-Item -Path M:\MSSQL\Data\WWI_UserData1.ndf N:\MSSQL\Data\WWI_UserData1.ndf'
										  ,@database_name = N'master'
										  ,@flags = 0
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback /****** Object: Step [ModifyFile and Bring Online] Script Date: 7/12/2018 12:46:47 AM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @jobId
										  ,@step_name = N'ModifyFile and Bring Online'
										  ,@step_id = 3
										  ,@cmdexec_success_code = 0
										  ,@on_success_action = 1
										  ,@on_success_step_id = 0
										  ,@on_fail_action = 2
										  ,@on_fail_step_id = 0
										  ,@retry_attempts = 0
										  ,@retry_interval = 0
										  ,@os_run_priority = 0
										  ,@subsystem = N'TSQL'
										  ,@command = N' ALTER DATABASE BranchDB MODIFY FILE ( NAME = WWI_UserData, FILENAME = ''N:\MSSQL\Data\WWI_UserDataNew.ndf'' );
ALTER DATABASE BranchDB SET ONLINE;'
										  ,@database_name = N'master'
										  ,@flags = 0
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId
										 ,@start_step_id = 1
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId
											,@server_name = N'(local)'
IF (@@error <> 0
	OR @ReturnCode <> 0)
	GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@trancount > 0)
	ROLLBACK TRANSACTION
EndSave:
GO

Conclusion

Dans cet article, nous avons vu une façon de déplacer les fichiers de base de données utilisateur dans SQL Server. Nous avons également constaté la nécessité de nous assurer que nous prêtons attention aux autorisations sur le fichier de données au nouvel emplacement afin de ne pas rencontrer d'erreurs lors de la remise en ligne de la base de données. Nous avons également vu que nous pouvons mettre tout cela dans un travail SQL Server Agent en utilisant les sous-systèmes T-SQL et PowerShell. Dans un article ultérieur, nous verrons deux autres méthodes pour déplacer des fichiers de base de données vers un nouveau volume.

Pour en savoir plus :

Déplacer des fichiers de données dans SQL Server – Partie 2