Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách di chuyển tệp dữ liệu trong SQL Server - Phần 1

Giới thiệu

Có một số tình huống sẽ đảm bảo việc di chuyển các tệp cơ sở dữ liệu hoặc tệp nhật ký giao dịch từ ổ đĩa này sang ổ đĩa khác trên cùng một máy chủ. Chúng có thể bao gồm:

  1. Sự cần thiết phải định dạng ổ đĩa giả sử nó không được định dạng đúng khi SQL Server được cài đặt . Nhớ lại rằng khi cài đặt SQL Server, nên sử dụng kích thước đơn vị phân bổ 64K để định dạng các ổ đĩa. Nếu điều này không được thực hiện tại thời điểm cài đặt và cần được thực hiện sau đó, thì rõ ràng nó sẽ yêu cầu giữ lại bản sao lưu của cơ sở dữ liệu hoặc tạo một tập mới, được định dạng đúng và di chuyển cơ sở dữ liệu sang tập mới này.
  2. Nhu cầu sử dụng một ổ đĩa mới giả sử đã đạt đến giới hạn cho bộ nhớ cơ bản . Một ví dụ điển hình là giới hạn 2TB của VMware Data Store. Đây là trường hợp của VSphere 5.0. Các phiên bản cao hơn của VSphere có giới hạn cao hơn nhiều.
  3. Sự cần thiết phải cải thiện hiệu suất bằng cách quản lý IO . Một lý do nữa mà bạn có thể muốn di chuyển các tệp dữ liệu là hiệu suất. Có những trường hợp cơ sở dữ liệu được tạo với nhiều tệp dữ liệu cùng nằm trên một đĩa cho đến khi nó trở nên rõ ràng, khi cơ sở dữ liệu phát triển, rằng bạn đã tạo một “vùng nóng” trong lớp lưu trữ. Một giải pháp sẽ là tạo các tệp dữ liệu mới và xây dựng lại các chỉ mục theo nhóm, một giải pháp khác là di chuyển các tệp dữ liệu.

Tình huống một:Di chuyển cơ sở dữ liệu người dùng

Các bước liên quan đến việc di chuyển cơ sở dữ liệu người dùng bao gồm những điều sau:

  1. Đưa cơ sở dữ liệu vào chế độ ngoại tuyến
  2. Cập nhật danh mục hệ thống với vị trí mới
  3. Sao chép vật lý tệp dữ liệu vào vị trí mới
  4. Đưa cơ sở dữ liệu trực tuyến

Liệt kê 1 cho thấy các lệnh được thực hiện để đạt được các bước này.

Danh sách 1 tệp dữ liệu di chuyển

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

Điều quan trọng cần lưu ý là khi sử dụng cơ sở dữ liệu ngoại tuyến, số lượng phiên hoạt động có thể làm chậm quá trình. Lập lịch thời gian ngừng hoạt động để thực hiện tác vụ này sẽ là một ý kiến ​​hay. Trong thời gian ngừng hoạt động như vậy, chủ sở hữu ứng dụng nên dừng các dịch vụ ứng dụng kết nối với cơ sở dữ liệu trước khi DBA cố gắng đưa cơ sở dữ liệu vào ngoại tuyến. Có những trường hợp không thuận tiện lắm khi đưa cơ sở dữ liệu vào ngoại tuyến, thì tắt phiên bản sẽ là lựa chọn tốt nhất. Trong trường hợp như vậy, cách tiếp cận sẽ hơi khác một chút:

  1. Cập nhật danh mục hệ thống với vị trí mới
  2. Tắt phiên bản
  3. Sao chép vật lý tệp dữ liệu mong muốn sang vị trí mới
  4. Khởi động phiên bản

Trong cả hai cách tiếp cận, khái niệm đều giống nhau:nó liên quan đến việc cập nhật danh mục hệ thống trong cơ sở dữ liệu chính và sau đó định vị lại một cách vật lý tệp dữ liệu mong muốn. Trong cả hai trường hợp, tệp dữ liệu phải được đóng sạch. Hãy cùng xem các bước liên quan đến cách tiếp cận đầu tiên.

Hình 1 Xác minh vị trí của các tệp dữ liệu

Bước đầu tiên sẽ là kiểm tra trạng thái của sự vật để bắt đầu. Tiến hành đặt cơ sở dữ liệu ngoại tuyến và sửa đổi danh mục hệ thống.

Hình 2 Đặt Cơ sở dữ liệu Ngoại tuyến và Sửa đổi Danh mục

Như đã thấy trong Hình 3, sau khi chúng tôi cập nhật danh mục, truy vấn sys.master_files cho chúng tôi biết vị trí mới mà cơ sở dữ liệu chính mong đợi tệp dữ liệu sẽ ở trong đó cho dù chúng tôi có di chuyển tệp về mặt vật lý hay không. Trong Hình 4, chúng ta cũng thấy rằng không thể đưa cơ sở dữ liệu trực tuyến mà không di chuyển tệp đến vị trí mới về mặt vật lý trước (và đổi tên tệp để khớp với tên mới được chỉ định trong danh mục).

Hình. 3 Vị trí tệp mới

Hình 4 Thiếu tệp

Chúng tôi cũng muốn chỉ ra rằng khi chúng tôi sao chép tệp, chúng tôi sẽ mất các quyền trước đó đối với tệp và SQL Server sẽ không thể mở tệp khi chúng tôi cố gắng đưa cơ sở dữ liệu trực tuyến. Chúng tôi phải chỉnh sửa các quyền đối với tệp và thêm cấp cho tài khoản NT SERVICE \ MSSQLSERVER quyền đầy đủ đối với tệp.

Hình 5 Sao chép tệp dữ liệu

Hình 6 Quyền tại Điểm đến

Hình 7a Quyền tại Nguồn

Hình 7b Quyền tại Nguồn

Nếu chúng tôi cố gắng đưa cơ sở dữ liệu trực tuyến trở lại với những quyền này bị thiếu, chúng tôi sẽ gặp lỗi 0x5 (Access Denied). Nếu chúng ta phải làm điều gì đó như di chuyển tệp dữ liệu bằng cách sử dụng công việc tác nhân, chúng tôi thấy rằng tài khoản SQL Server Agent có quyền sở hữu tệp và chúng tôi chỉ có thể đưa cơ sở dữ liệu vào vì tài khoản SQL Server Agent giống với Tài khoản SQL Server.

Hình 8 Quyền truy cập bị từ chối trên tệp dữ liệu mới

Giả sử bạn đang cố gắng đưa cơ sở dữ liệu trực tuyến bằng SSMS GUI, bạn sẽ thấy những lỗi này trong Trình xem sự kiện cũng như trong nhật ký lỗi SQL Server nếu bạn quan sát kỹ. Ngoài ra, nếu bạn đang sử dụng cách tiếp cận thứ hai (khởi động lại toàn bộ phiên bản), bạn sẽ thấy rằng cơ sở dữ liệu sẽ bị kẹt ở giai đoạn khôi phục. Kiểm tra Nhật ký lỗi sẽ cho bạn biết điều gì đang thực sự xảy ra.

Liệt kê 2 Di chuyển tệp dữ liệu bằng công việc đại lý

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

Hình 9 Quyền đối với tệp dữ liệu khi sử dụng công việc đại lý

Hình 10 Cơ sở dữ liệu trực tuyến

Tự động hóa quy trình

Để cho vui, chúng ta có thể quyết định sử dụng SQL Server Agent Job cho toàn bộ quá trình. Chúng tôi định cấu hình một bước công việc cho mỗi bước trong quy trình của chúng tôi. Điều này có thể hữu ích nếu bạn muốn trở thành một DBA siêu sao và lên lịch di chuyển như vậy qua đêm trong khi bạn về nhà và thư giãn với gia đình. Chắc chắn bạn muốn đảm bảo rằng bạn định cấu hình thông báo để kích hoạt khi công việc thành công để bạn chắc chắn rằng nó thực sự hoàn thành khi bạn vắng nhà.

Liệt kê 3 Thực hiện Tác vụ bằng Công việc Đại diện

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

Kết luận

Trong bài viết này, chúng ta đã thấy một cách để di chuyển tệp cơ sở dữ liệu người dùng trong SQL Server. Chúng tôi cũng nhận thấy sự cần thiết phải đảm bảo rằng chúng tôi chú ý đến các quyền trên tệp dữ liệu tại vị trí mới để chúng tôi không gặp phải lỗi khi đưa cơ sở dữ liệu trực tuyến trở lại. Chúng tôi cũng đã thấy rằng chúng tôi có thể đưa tất cả những thứ này vào công việc SQL Server Agent bằng cách sử dụng Hệ thống con T-SQL và PowerShell. Trong bài viết tiếp theo, chúng ta sẽ thấy hai phương pháp khác để di chuyển các tệp cơ sở dữ liệu sang một ổ đĩa mới.

Đọc thêm:

Di chuyển tệp dữ liệu trong SQL Server - Phần 2


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mọi khóa ngoại của SQL Server có nên có một chỉ mục phù hợp không?

  2. Điểm kiểm tra cơ sở dữ liệu trong SQL Server

  3. Tạo Trigger để ghi SQL mà bảng bị ảnh hưởng?

  4. Trả lại tất cả các cột không được tính toán từ một bảng trong SQL Server

  5. Lệnh SQL INSERT đang hoạt động nhưng dữ liệu không xuất hiện trong bảng