sql >> Database >  >> RDS >> Sqlserver

Gegevensbestanden verplaatsen in SQL Server - Deel 1

Inleiding

Er zijn een aantal situaties die het verplaatsen van databasebestanden of transactielogbestanden van het ene volume naar het andere op dezelfde server rechtvaardigen. Deze kunnen zijn:

  1. De noodzaak om het volume te formatteren in de veronderstelling dat het niet correct was geformatteerd toen SQL Server werd geïnstalleerd . Bedenk dat bij het installeren van SQL Server het wordt aanbevolen om de grootte van de toewijzingseenheid van 64 kB te gebruiken om de volumes te formatteren. Als dit niet wordt gedaan op het moment van installatie en later moet worden gedaan, moet er uiteraard een back-up van de database worden bewaard of moet een nieuw, correct geformatteerd volume worden gemaakt en de database naar dit nieuwe volume worden verplaatst.
  2. De noodzaak om een ​​nieuw volume te gebruiken, ervan uitgaande dat de limieten voor de onderliggende opslag zijn bereikt . Een goed voorbeeld is de 2TB-limiet van een VMware Data Store. Dit is het geval vanaf Vsphere 5.0. Hogere versies van Vsphere hebben veel hogere limieten.
  3. De noodzaak om de prestaties te verbeteren door IO te beheren . Nog een reden waarom u gegevensbestanden wilt verplaatsen, zijn de prestaties. Er zijn gevallen waarin een database wordt gemaakt met meerdere gegevensbestanden die allemaal op één schijf staan ​​totdat het duidelijk wordt, naarmate de database groeit, dat u een "hot region" in de opslaglaag hebt gecreëerd. Een oplossing zou zijn het maken van nieuwe gegevensbestanden en het opnieuw opbouwen van geclusterde indexen, een andere zou het verplaatsen van gegevensbestanden zijn.

Scenario één:gebruikersdatabases verplaatsen

De stappen bij het verplaatsen van een gebruikersdatabase omvatten de volgende:

  1. De database offline halen
  2. Update de systeemcatalogus met de nieuwe locatie
  3. Kopieer het gegevensbestand fysiek naar de nieuwe locatie
  4. Breng de database online

Lijst 1 toont de uitgevoerde commando's om deze stappen te bereiken.

Lijst 1 Gegevensbestanden verplaatsen

-- 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');

Het is belangrijk op te merken dat bij het offline halen van een database het aantal actieve sessies het proces kan vertragen. Het zou een goed idee zijn om een ​​downtime te plannen om deze taak uit te voeren. Tijdens een dergelijke uitvaltijd moet de eigenaar van de toepassing de verbinding van de toepassingsservices met de database stopzetten voordat de DBA probeert de database offline te halen. Er zijn gevallen waarin het niet zo handig is om de database offline te halen, dan is het afsluiten van de instance de beste optie. In zo'n geval zou de aanpak iets anders zijn:

  1. Update de systeemcatalogus met de nieuwe locatie
  2. Sluit de instantie af
  3. Kopieer het gewenste databestand fysiek naar de nieuwe locatie
  4. Start de instantie op

In beide benaderingen is het concept hetzelfde:het gaat om het bijwerken van de systeemcatalogus in de hoofddatabase en het vervolgens fysiek verplaatsen van het gewenste gegevensbestand. In beide gevallen moet het databestand netjes worden afgesloten. Laten we eens kijken naar de stappen bij de eerste benadering.

Fig. 1 Controleer de locatie van gegevensbestanden

De eerste stap zou zijn om te beginnen met het controleren van de stand van zaken. Ga verder om de database offline te zetten en de systeemcatalogus aan te passen.

Fig. 2 Database offline instellen en catalogus wijzigen

Zoals te zien is in Fig. 3, vertelt het opvragen van sys.master_files ons, zodra we de catalogus hebben bijgewerkt, de nieuwe locatie waar de hoofddatabase verwacht dat het gegevensbestand zich bevindt, ongeacht of we het bestand fysiek hebben verplaatst. In Fig. 4 zien we ook dat het niet mogelijk is om de database online te brengen zonder eerst het bestand fysiek naar de nieuwe locatie te verplaatsen (en het bestand te hernoemen zodat het overeenkomt met de nieuwe naam die in de catalogus is gespecificeerd).

Fig. 3 Nieuwe bestandslocaties

Afb. 4 Ontbrekend bestand

We willen er ook op wijzen dat zodra we het bestand kopiëren, we de eerdere machtigingen op het bestand verliezen en SQL Server het bestand niet kan openen wanneer we proberen de database online te brengen. We moeten de bestandsmachtigingen bewerken en het account NT SERVICE\MSSQLSERVER volledige machtigingen voor het bestand verlenen.

Fig. 5 Kopieer het gegevensbestand

Fig. 6 Toestemmingen op bestemming

Fig. 7a Toestemmingen bij de bron

Fig. 7b Toestemmingen bij de bron

Als we zouden proberen om de database weer online te brengen terwijl deze machtigingen ontbreken, krijgen we een foutmelding 0x5 (Toegang geweigerd). Als we zoiets zouden doen als het gegevensbestand verplaatsen met behulp van een agenttaak, zien we dat het SQL Server Agent-account het eigendom van het bestand verwerft en dat we de database alleen kunnen brengen omdat het SQL Server Agent-account hetzelfde is als het SQL Server-account.

Fig. 8 Toegang geweigerd op nieuw gegevensbestand

Ervan uitgaande dat u probeerde de database online te brengen met behulp van de SSMS GUI, zou u deze fouten zowel in Logboeken als in het foutenlogboek van SQL Server zien als u goed kijkt. Bovendien, als u de tweede benadering zou gebruiken (het hele exemplaar opnieuw opstarten), zou u zien dat de database vast zou blijven zitten in de herstelfase. Als u het foutenlogboek bekijkt, weet u wat er werkelijk aan de hand is.

Opsomming van 2 gegevensbestanden verplaatsen met behulp van een agenttaak

/* ==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 Rechten op gegevensbestand bij gebruik van Agent Job

Afb. 10 Database online

Het proces automatiseren

Gewoon voor de lol kunnen we besluiten om SQL Server Agent Job voor het hele proces te gebruiken. We configureren een taakstap voor elke stap van ons proces. Dit kan handig zijn als u een superster-DBA wilt zijn en een dergelijke migratie 's nachts wilt plannen terwijl u naar huis gaat en met familie ontspant. U wilt er zeker van zijn dat u een melding configureert die wordt geactiveerd wanneer de taak slaagt, zodat u zeker weet dat deze ook daadwerkelijk wordt uitgevoerd terwijl u weg bent.

Lijst 3 De taak uitvoeren met een agenttaak

/* ==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

Conclusie

In dit artikel hebben we een manier gezien om gebruikersdatabasebestanden in SQL Server te verplaatsen. We hebben ook de noodzaak gezien om ervoor te zorgen dat we aandacht besteden aan de rechten op het databestand op de nieuwe locatie, zodat we geen fouten tegenkomen bij het weer online brengen van de database. We hebben ook gezien dat we deze allemaal in een SQL Server Agent-taak kunnen plaatsen met behulp van de T-SQL- en PowerShell-subsystemen. In een volgend artikel zullen we twee andere methoden zien om databasebestanden naar een nieuw volume te verplaatsen.

Verder lezen:

Gegevensbestanden verplaatsen in SQL Server – Deel 2


  1. Hoe een kolom in een tabel in SQL toe te voegen?

  2. SQLiteOpenHelper:methode onCreate() niet aangeroepen op fysiek apparaat

  3. Werken uw medewerkers op afstand? Hier leest u hoe u uw gegevens veilig kunt houden.

  4. Hoe percentage te berekenen met een SQL-statement