2023年11月15日 星期三

SQL Server 2019 容錯移轉叢集環境架設 - 整合 Windows 2022 iSCSI Target Server 的功能

        我在之前有介紹關於許多 SQL Server 容錯移轉叢集環境架設的部份,而且用了許多的篇幅詳細的介紹,但隨著版本的更新,我們來介紹不同的安裝方式,但目前此篇的方法,比較適合測試環境,我是為了有一個對照的環境可以測試,但在正式機上,可能還是要考量一下,目前仍不建議透過此篇的方式進行,如果真的要選擇的話,其實透過 AlwaysOn,反而是一個比較推薦的作法,大家也可以參考下列的文章。


前篇介紹:

  1. SQL Server 2008 R2 容錯移轉叢集環境架設 - 利用 VM 與 Windows Storage Server - Part I
  2. SQL Server 2008 R2 容錯移轉叢集環境架設 - 利用 VM 與 Windows Storage Server - Part II
  3. SQL Server 2008 R2 容錯移轉叢集環境架設 - 利用 VM 與 Windows Storage Server - Part III(終)
  4. 容錯移轉叢集中多個節點切換順序的設定

AlwaysOn相關設定文章:

  1. 在混合雲的架構上建立完整的AlwaysOn架構
  2. SQL Server 2012 新功能 - AlwaysOn安裝與設定


架構說明:

此架構上,目前有一台 AD + 二台 SQL Server Nodes + Windows 2022 iSCSI Target Server,總共有四台主機,如下列所示。

  • AD: Windows Server 2022
  • SQL Server: Windows Server 2022 + SQL Server 2019
  • iSCSI Target Server: Windows 2022 iSCSI Target Server

安裝開始:

1. 請先至 iSCSI Target Server 主機,新增 iSCSI Target Server 的功能


2. 功能啟用完成後,開始設定 iSCSI disk

3. 選擇 iSCSI disk 建立在那一個實體磁碟上

4. 設定 iSCSI disk 磁碟名稱,在這邊我會建立二顆磁碟,一顆為 仲裁磁碟 (Quorum Disk),另一顆為資料庫資料磁碟

5. 設定磁碟的大小,這邊設定的是最大的可用容量,實際上一開始會很小,但最大可使用到此設定空間。

6. 指定 iSCSI target,由於目前系統不存在,所以進行新增

7. 指定 iSCSI target 的名稱

8. 設定有那些主機可以連線到此 iSCSI target server,所以要將二台 SQL Server 加入,其實後續的設定也可以隨時進行調整

9. 設定用戶端連線到 iSCSI target server 時,是否需要額外的帳號密碼 (CHAP),這邊設定我就沒有特別啟用。


10. 等待系統設定啟用完成

11. 設定完成後,即可以在上方看到有二個 iSCSI 磁碟

12. iSCSI target server 設定完成後,即可設定用戶端,也就是二台 SQL Server,我們先設定第一台,登入後,點選 iSCSI initiator 即可,這個不需額外的安裝即可使用

13. 執行 iSCSI initiator 時,由於預設服務是沒有啟用的,所以會跳出下列的訊息,點選 "Yes" 後 即會啟動服務 


14. 在下列的 Target 區域,輸入 iSCSI target server 的 IP 位置,然後點選 Quick Connect

15. 連結成功後,即可在 Disk Management 中看到之前設定的 iSCSI disk,在此設定 online 與 格式化後,即可以使用。

16. 設定好磁碟後,回到 iSCSI initiator 的 Volume and Devices 點選 Auto Configure,設定完第一台之後,也同時設定第二台,這樣即可

17. 二台都設定完成後,即可設定容錯移轉叢集,完成後,即可看到叢集中有二個節點與二個磁碟,此時也可以嘗試進行 容錯轉移,確認一切都正常。


18. 設定完成 容錯移轉叢集 之後,即可進行 SQL Server 的安裝,在安裝第一個節點時,請選擇 "新的 SQL Server 容錯移轉叢集安裝" 進行。


19. 完成後,即可看到 容錯移轉叢集 中的 Roles 出現 SQL Server,此時即完成第一台,然後再進行第二台的設定。


20. 在進行第二台 SQL Server 的安裝時,請選擇用 "將節點加入到 SQL Server 容錯移轉叢集" 的方式進行,而由於第一台的 Python 與 R 安裝失敗,雖然不影響後續的使用,但在第二台安裝時,會遇到下列的錯誤,雖然我有確認第一台的服務有啟動成功,但一樣會遇到下列的錯誤。

SQL Server Database Services feature state "failed"

21. 這個問題,主要是由於第一台安裝沒有完整的完成,所以才會有這個訊息,解決方法上,可以除了確認第一台的安裝問題為何外,也可以透過下列的方式進行解決。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL15.MSSQLSERVER\ConfigurationState

這個機碼下有多個服務的狀態值,如同下列的圖示,將 2 的部份改成 1,然後再點選一次 "Re-Run" 即可通過。


22. 透過 Process Monitor 觀察,其實安裝時,系統是透過 remote registry 的方式存取此區判斷

23. 第二台安裝完成後,即可嘗試進行 容錯轉移 的動作,確認是否都安裝完成

2023年11月10日 星期五

如何透過 Partition Table 進行資料分散與維護作業並以年度為例

        先前一篇針對 Partition Table 進行詳細的介紹,近日再重新的檢示,其實我覺得自已當初提出的資料平均分配的方式很好,而且其實到現在還是很適用,但由於有很多的客戶需求,希望可以透過日期的方式來進行資料分散與切割,所以今天我就透過這篇來特別介紹一下。

如何在 AlwaysOn 建立 Partition Table 與自動進行資料平均分配http://caryhsu.blogspot.com/2016/01/alwaysonpartition-table.html

此篇我們透過 AdventureWorks 的資料庫來進行,並且也會說明在建立後,如果遇到新年度時,大佬與預算較緊的使用者們,針對透過年月的方式進行資料分散的方式,該如何維護,這篇也會詳細的介紹。

本篇在 Partition Table 建立後,其實維護是最麻煩的,由其在 MergeSplit 的部份,我其實也是在測試機上測試了好多次,才摸清最好與最佳的方式,希望二篇加起來後,可以更完整的幫助到大家。

1。 加入 file group 與 files,這邊建議將 file 分散至不同的卷上面,最好的情況是有四台實體磁碟,各自放一個 file。

USE [master]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILEGROUP [ag_group_1]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILEGROUP [ag_group_2]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILEGROUP [ag_group_3]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILEGROUP [ag_group_4]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILE ( NAME = N'fg_1', FILENAME = N'C:\sql_data\fg_1.ndf' , SIZE = 51200KB , FILEGROWTH = 1024KB ) TO FILEGROUP [ag_group_1]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILE ( NAME = N'fg_2', FILENAME = N'C:\sql_data\fg_2.ndf' , SIZE = 51200KB , FILEGROWTH = 1024KB ) TO FILEGROUP [ag_group_2]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILE ( NAME = N'fg_3', FILENAME = N'C:\sql_data\fg_3.ndf' , SIZE = 51200KB , FILEGROWTH = 1024KB ) TO FILEGROUP [ag_group_3]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILE ( NAME = N'fg_4', FILENAME = N'C:\sql_data\fg_4.ndf' , SIZE = 51200KB , FILEGROWTH = 1024KB ) TO FILEGROUP [ag_group_4]
GO

2. 由於目前有四個資料群組,所以我們先統計一下資料量,然後再來規畫一下如何分散資料,目前如下圖,主要有2013年7月至2014年8月的資料。

--統計資料分佈

SELECT left(convert(varchar,TransactionDate,112),6) [tdhyear], count(*) nums
FROM [AdventureWorks2019].[Production].[TransactionHistory]
group by  left(convert(varchar,TransactionDate,112),6)
order by 1,2


3. 建立 Partition FunctionPartition Schema,這邊會建立三個區域與對應至四個 File Group,如下列所示。

1900-01-01 00:00:00.000 ~ 2013-10-01 00:00:00.000 -> 儲存至 ag-group_1
2013-10-01 00:00:00.000 ~ 2014-02-01 00:00:00.000 -> 儲存至 ag-group_2
2014-02-01 00:00:00.000 ~ 2014-04-01 00:00:00.000 -> 儲存至 ag-group_3
2014-04-01 00:00:00.000 ~ 日後所有 -> 儲存至 ag-group_4

--將資料平均分散在多個不同區間

use [AdventureWorks2019];
CREATE PARTITION FUNCTION [PF-cary-test](datetime) AS RANGE RIGHT FOR VALUES (N'2013-10-01T00:00:00', N'2014-02-01T00:00:00', N'2014-04-01T00:00:00')

PS: 這裡建議採用 RANGE RIGHT 的方式,而不是用 RANGE Left, 因為我在 SQL Server 2019 與 2022 上測試,當使用 RANGE Left 的方式時,如果進行 SPLIT RANGE時,你會發現 ALTER PARTITION SCHEME 中的 NEXT USED 當合併資料,並將新加入的 file 與前一個 file 互換,雖然這樣也是沒問題,但還是覺得怪怪的,所以這邊也再請注意一下。

CREATE PARTITION SCHEME [PS-cary-test] AS PARTITION [PF-cary-test] TO ([ag_group_1], [ag_group_2], [ag_group_3], [ag_group_4])

4. 建立完上述的動作後,資料並不會立即的進行資料的搬移,需透過移除 Clustered Index 後,再將索引重新加入後即可

此處原本 TransactionID 是 PK 與 CLUSTERED INDEX,但由於此處的 Partition Table 是根據 TransactionDate 進行分配,所以要將 CLUSTERED INDEX 換成 TransactionDate 之後,資料才會重新進行排序。

ALTER TABLE [Production].[TransactionHistory] DROP CONSTRAINT [PK_TransactionHistory_TransactionID] WITH ( ONLINE = OFF )

ALTER TABLE [Production].[TransactionHistory] ADD  CONSTRAINT [PK_TransactionHistory_TransactionID] PRIMARY KEY NONCLUSTERED
(

[TransactionID] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

CREATE CLUSTERED INDEX [ClusteredIndex_on_PS-cary-test_638351445508081513] ON [Production].[TransactionHistory]
(

[TransactionDate]

)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PS-cary-test]([TransactionDate])

DROP INDEX [ClusteredIndex_on_PS-cary-test_638351445508081513] ON [Production].[TransactionHistory]

5. 透過下列的語法進行查詢,並確認資料在各群組分配的情況

SELECT OBJECT_NAME(p.object_id) AS ObjectName ,
i.name AS IndexName ,p.index_id AS IndexID ,
ds.name AS PartitionScheme ,
p.partition_number AS PartitionNumber ,
fg.name AS FileGroupName ,
prv_left.value AS LowerBoundaryValue ,
prv_right.value AS UpperBoundaryValue ,
CASE pf.boundary_value_on_right
WHEN 1 THEN 'RIGHT'
ELSE 'LEFT'
END AS PartitionFunctionRange ,
p.rows AS Rows
FROM sys.partitions AS p
INNER JOIN sys.indexes AS i ON i.object_id = p.object_id
AND i.index_id = p.index_id
INNER JOIN sys.data_spaces AS ds ON ds.data_space_id = i.data_space_id
INNER JOIN sys.partition_schemes AS ps ON ps.data_space_id = ds.data_space_id
INNER JOIN sys.partition_functions AS pf ON pf.function_id = ps.function_id
INNER JOIN sys.destination_data_spaces AS dds ON dds.partition_scheme_id = ps.data_space_id
AND dds.destination_id = p.partition_number
INNER JOIN sys.filegroups AS fg ON fg.data_space_id = dds.data_space_id
LEFT OUTER JOIN sys.partition_range_values AS prv_left ON ps.function_id = prv_left.function_id AND prv_left.boundary_id = p.partition_number- 1
LEFT OUTER JOIN sys.partition_range_values AS prv_right ON ps.function_id = prv_right.function_id AND prv_right.boundary_id = p.partition_number
WHERE p.object_id = OBJECT_ID('Production.TransactionHistory');


6。 從查詢上來看,後續未規畫的資料年度就會放置到最後一個 file group,所以當新年度到達時,通常我們會採取二種不同的作法,一時加入一個 file group,然後將後續的資料加入,另一種就是合併資料,並將新年度的資料轉向最後一個 file group中,所以也在這分別說明二種方式。

7。 課長級作法。也就是加入一個 file 並將新年度的資料轉至此新的 file 中

7-1. 加入新的 file group

use [master];
ALTER DATABASE [AdventureWorks2019] ADD FILEGROUP [ag_group_5]
GO

ALTER DATABASE [AdventureWorks2019] ADD FILE ( NAME = N'fg_5', FILENAME = N'C:\sql_data\fg_5.ndf' , SIZE = 51200KB , FILEGROWTH = 1024KB ) TO FILEGROUP [ag_group_5]
GO

7.2 將新的 file group 加入至 schema 中,並分割出新的資料區間時區,就是將 '2015-01-01' 後的時間,儲存至新的 file 中

use [AdventureWorks2019];
ALTER PARTITION SCHEME [PS-cary-test]
NEXT USED ag_group_5;

ALTER PARTITION FUNCTION  [PF-cary-test] () 
SPLIT RANGE ('2015-01-01T00:00:00.000')

7-3 查詢資料分佈的情況

8. 微課長級的作法,如果無法增加新的 file 用來分散資料的話,可以透過資料合併的方式,然後將新的資料儲存至最後一個群組中

8-1 依照資料上的分佈,我先將 file 3 與 4 的資料先進行合併,所以這邊我將 2014-02-01 00:00:00.000 之後的資料先合併至 ag-group3

ALTER PARTITION FUNCTION [PF-cary-test] () 
MERGE RANGE ('2014-04-01 00:00:00.000');

8-2 將 2015-01-01 之後的資料存到 ag-group4 上面

ALTER PARTITION SCHEME [PS-cary-test]
NEXT USED ag_group_4;

ALTER PARTITION FUNCTION  [PF-cary-test] () 
SPLIT RANGE ('2015-01-01T00:00:00.000'); 

8-3 由於有作過資料合併的動作,所以最好也是手動更新一次統計資訊

UPDATE STATISTICS [Production].[TransactionHistory]

8-4 查詢資料分佈的情況

2023年11月8日 星期三

SQL Server 啟動帳號最佳實踐與最小化權限設定

        此篇文章主要是最近經過二位大師的指導,修正一些以前的概念,自已嘗試作過一次後,發現其中其實有許多的坑,沒有作過一次,真的很難說有 100% 的懂 (我自已),而且作完後有更深的體驗,所以整理成此篇,相信這也是企業內日後主推的部份,也希望大家可以參考並套用在企業中。        

預設的情況下,SQL Server 的啟動帳號為 NT Service\MSSQLSERVER,而在網域的架構上,許多人會設定為網域帳號,如常見的 Domain User + Local Admin,但這樣的設定在安全性與稽核上,存在著許多的問題。

在許多的公司,常見的情況,通常會規定不能使用 Local Admin,而且規定每一個帳號 60 or 90 天後要重新設定密碼,所以以前常遇到客戶提出SQL重啟後,無法正常啟動,常見遇到的就是密碼過期等情況,所以造成無法啟動。

另外如果 SQL Server 的啟動帳號權限設定的太大,一但遇到如 SQL Injection 等的攻擊時,容易會造成更大的問題,因為會被當作跳板,再進行其他主機的攻擊,所以最小化的權限設定,將可以有效的防止等問題的發生。

最後許多的系統管理員要維護自已的帳號與密碼於 Excel or 筆記本中,而且在固定的時間就要進行更新,這種明碼存在的方式,也是另一個安全性的隱憂。

講了這麼多,我們就講主題,在啟動帳號的部份,微軟 (Microsoft) 強烈的推薦透過 受控服務帳戶 (Managed Service Accounts) 與 群組受控服務帳戶 (Group Managed Service Accounts) 來進行,如同我上述的介紹,這二個帳號類型就符合我提到的部份,在使用這二個帳號類型前,我們也來說看一下最低限制。

Group Managed Service Account Prerequisites:

  • Domain Functional Level of 2012 or higher
  • SQL Server 2014 or higher
  • Window Server 2012 R2 Operating System

另外受控服務帳戶 (Managed Service Accounts) 與 群組受控服務帳戶 (Group Managed Service Accounts) 在設定上,也不需要手動輸入密碼,不需要再透過 Excel 等筆記本來記錄帳號密碼等,而密碼的部份也是每30天自動更新,二個帳號一個應用於單機的環境,而另一個則是應用於 HA 等的架構,如 WSFC、AlwaysOn 等群組節點的情境,所以本篇將透過  群組受控服務帳戶 (Group Managed Service Accounts) 與 AlwaysOn 的環境來進行設定。

1. 登入主要網域進行下列的設定

2. 首先檢查 KDS (Key Distribution Service) 是否有 Root Key 的存在。 

Test-KdsRootKey -KeyId (Get-KdsRootKey).KeyId

如果存在的話,會傳回 "True",如果沒有的話,就需要進行下列設定。

Add-KdsRootKey –EffectiveTime ((get-date).addhours(-10))
or
Add-KdsRootKey -EffectiveImmediately

3. 也可以透過下列的指令查詢目前所有的 KDS KEY

Get-KdsRootKey

4. 建立一個群組,並將二個 SQL 節點加入群組中。

New-ADGroup -Name gmsa-sql-alwayson -Description "Security group for gMSAsql computers" -GroupCategory Security -GroupScope Global

4-1 將 SQL 節點加入群組中。

Add-ADGroupMember -Identity gmsa-sql-alwayson -Members SQL2019-AG1$,SQL2019-AG2$

PS: 上述的 SQL2019-AG1$ 是第一台節點,SQL2019-AG2$ 為第二個節點。

4-2 透過下列的語法查詢目前此群組中的成員有那些。

Get-ADGroupMember -Identity gmsa-sql-alwayson

4-3 也可以透過 Active Directory Users and Computers 介面的方式進行檢示。

5. 建立 群組受控服務帳戶 (Group Managed Service Accounts)

New-ADServiceAccount -name gMSAsql -DNSHostName gMSAsql.mscaryhsu.com -PrincipalsAllowedToRetrieveManagedPassword gmsa-sql-alwayson

Get-ADServiceAccount gMSAsql -Property PasswordLastSet

PS: 上述你也可以查詢到此帳號密碼最後更新的時間

6. 設定此 群組受控服務帳戶 (Group Managed Service Accounts可以擁有註冊 SPN 的權限,這個非常的重要,後面我們也會確認是否在更換帳號後可以正確的註冊 SPN.  

dsacls (Get-ADServiceAccount -Identity gMSAsql).DistinguishedName /G "SELF:RPWP;servicePrincipalName"

7. 一切設定完成後,必須到各自的節點進行套用,我們先登入到第一台節點,再登入到第二個節點進行即可。

8.  啟用 Windows 的功能

8-1 檢查功能是否已啟用

PS C:\> Get-WindowsFeature AD-Domain-Services

Display Name                           Name                Install State
------------                           ----                -------------
[ ] Active Directory Domain Services   AD-Domain-Services  Available


8-2 啟用此功能

PS C:\Users\Administrator> Add-WindowsFeature AD-Domain-Services

Display Name                                            Name                       Install State
------------                                            ----                       -------------
[X] Active Directory Domain Services                    AD-Domain-Services             Installed


9.  啟用 群組受控服務帳戶 (Group Managed Service Accounts)

Install-ADServiceAccount -Identity gMSAsql
Test-ADServiceAccount -Identity gMSAsql

10. 請至另一個節點也是完成 8與9 的步驟

11. 完成上述的步驟後,就已完成 群組受控服務帳戶 (Group Managed Service Accounts) 的設定,完成設定後,請至 SQL Server Configuration Manager 更換 SQL Server 的啟動帳號,請注意千萬不要透過系統中的服務列表進行更換,否則會有問題。


12. 更換完成後,目前已是最小權限,但仍建議進行作業系統上的系統原則,有二個是一定要設定的,要不然也是會因為權限不夠,而造成問題,一個是 啟用鎖定記憶體分頁選項 (Lock pages in memory) 與 執行磁碟區維護工作(Perform volume maintenance tasks),這二個設定也是在二個節點都需要進行。



執行磁碟區維護工作(Perform volume maintenance tasks)
執行磁碟區維護工作 - Windows Security | Microsoft Learn


13. 確認上述的二個設定是否有啟用成功

13-1 透過 SQL Server Error Log

2023-11-08 15:10:34.63 Server      Using locked pages in the memory manager.

13-2 透過 DMV 查詢是否有啟用成功

SELECT sql_memory_model, sql_memory_model_desc
FROM sys.dm_os_sys_info;

沒有啟用



啟用 Lock pages in memory



14. 另外在 SQL 各個服務的部份,下列的文章也有詳細的介紹所需的權限,這樣即可達到最小化權限的部份,目前我並沒有透過下列的文章進行,確認是沒有問題的,但仍建議在相關的目錄上,尤其是 SQL Server 的主要引擎的部份仍是需要進行設定。

Configure Windows service accounts and permissions
https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-windows-service-accounts-and-permissions?view=sql-server-ver16#GMSA

15. 最後我們也確認在 AlwaysOn 的部份也是一切正常,


16. 在權限的部份,網域帳號的群組,不是歸屬在 Domain Admin 中,而且也不歸屬在任何的群組中,而在 SQL Server 中,只有自動加入的電腦帳號,其中也只有 Connect 的權限而已,所以這部份絕對是最小化的權限。

2023年11月6日 星期一

啟用即時初始化檔案 (Instant file initialization) 的功能於 SQL Server 上

        即時初始化檔案 (Instant file initialization) 其實在 SQL Server 2005 就有提出,但隨著 SQL Server 版本的更新,此功能也不斷的更新與強化,所以此篇也特別介紹一下這個功能。

即時初始化檔案 (Instant file initialization) 主要說穿了,就是在建立資料庫 (Database) ,擴展空間或是還原資料庫等動作時,不進行磁碟初始化寫 zero 0 的動作,藉以加快初始化的動作,這樣一來在要求空間等動作時,可以加快申請的初始化動作,而且在 資料頁面(Data File) 的空間要求越大時,效果更是明顯,因為可以略過初始化填寫 zero 0 的動作。

通常有利也是有弊,我們在啟用這個功能時,也在深入的探討這個功能是否真的這麼強悍,但是否真的有適合不同的資料庫環境,我們分成下列的幾個方向進行討論。

1. 啟用此功能後是否會造成資料的錯寫或是錯亂等問題。

此功能持續觀察與使用已久,坦白說沒有遇過客戶回饋等問題,而且在相關的修正上,也沒有發現,所以這部份我覺得不是主要的問題。

2. 啟用後對效能上的影響,大約會有多少,是否有其他的負面影嚮。

此功能在啟用後,主要是進行相關動作時,不會針對 資料頁面(Data Page) 進行初始化寫 0 的動作,所以可以大大的加速擴展空間、建立資料庫、還原資料庫等動作,但是在負面影嚮的部份,我覺得主要是在安全性的部份,由於資料頁面沒有進一步的初始化,所以當有人透過此磁碟進行資料還原等動作時,是有可能可以查到之磁碟上原先存放的資料為何,這在有些管理上,可能是不允許的,也是有一定的風險存在的。

此功能在支援上,地端與雲端會有不同的支援程度,在雲端上,部份是沒有支援的,如 Azure 原本也是沒有支援的,但後來在 transaction log 的部份,是有 "部份" 支援的,但相對的 資料頁面(Data Page) 的部份,也是沒有支援的。

Database instant file initialization
Database instant file initialization - SQL Server | Microsoft Learn

另外在 AWS 上,很多人會透過 Amazon FSx for Windows File Server 來當作 SQL Disk 的部份,這部份也是沒有支援的,因為這個以前也有遇過客戶來討論過效能的問題,後來發現是不支援此功能,所以印像特別的深刻。

Using FSx for Windows File Server with Microsoft SQL Server
Using FSx for Windows File Server with Microsoft SQL Server - Amazon FSx for Windows File Server

說了這麼多,我們就來開始介紹如何進行啟用的方式。

在啟用的部份,你可以在一開始安裝時,在 Server Configuration 的部份,勾選 "Grant Perform Volme Maintenance Task privilege to SQL Server Database Engine Service" 的選項。


或是安裝完成後,從 SQL Server Configuration Manager -> SQL Server Service -> SQL Server(Instance name) -> Properties -> Advanced -> Instant File Initialization


另外在啟用時也請確認在作業系統層級,是否有權限進行套用,從 Local Security Policy -> Local Policies -> User Rights Assignment -> Perform volume maintenance tasks,請將你的 SQL Server 的啟動帳號加入此區的設定中即可。


設定完成後,你可以透過二個方式確認 SQL Server 是否有套用到 Instant file initialization 的功能。

1. 透過 SQL Server 的 Error Log 確認啟動時是否有套用此功能。

2023-11-03 18:02:37.12 Server      Database Instant File Initialization: enabled. For security and performance considerations see the topic 'Database Instant File Initialization' in SQL Server Books Online. This is an informational message only. No user action is required.

2. 透過 T-SQL 指令查詢是否有啟用 Instant file initialization

select servicename, status_desc, service_account, instant_file_initialization_enabled from sys.dm_server_services



一切準備就緒就後,我們可以來透過建立資料庫的方式,來比較二者間的差異,藉以了解在啟用後之間的差異。

--啟用 Trace Flag 將建立資料庫等資訊寫入至 SQL LOG 中。
DBCC TRACEON(3004 ,3605 ,-1);
GO

CREATE DATABASE [testIFI]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'testIFI', 
  FILENAME = N'C:\tmp\testIFI.mdf' , 
  SIZE = 40GB)
 LOG ON 
( NAME = N'testIFI_log', 
  FILENAME = N'C:\tmp\testIFI_log.ldf' , 
  SIZE = 20GB)
GO


輸出比對:
2023-11-03 17:52:14.76 Server      Database Instant File Initialization: disabled.
2023-11-03 17:54:39.78 spid64      Zeroing C:\tmp\testIFI.mdf from page 0 to 5242880 (0x0 to 0xa00000000)
2023-11-03 17:54:44.13 spid64      Zeroing completed on C:\tmp\testIFI.mdf (elapsed = 4347 ms)
2023-11-03 17:55:33.57 spid64      Zeroing C:\tmp\testIFI_log.ldf from page 0 to 2621440 (0x0 to 0x500000000)
2023-11-03 17:56:25.14 spid64      Zeroing completed on C:\tmp\testIFI_log.ldf (elapsed = 51562 ms)
2023-11-03 17:56:25.23 spid64      Starting up database 'testIFI'.
2023-11-03 17:56:25.26 spid64      Parallel redo is started for database 'testIFI' with worker pool size [1].
2023-11-03 17:56:25.26 spid64      FixupLogTail(progress) zeroing 2 from 0x5000 to 0x6000.
2023-11-03 17:56:25.26 spid64      Zeroing C:\tmp\testIFI_log.ldf from page 3 to 483 (0x6000 to 0x3c6000)
2023-11-03 17:56:25.27 spid64      Zeroing completed on C:\tmp\testIFI_log.ldf (elapsed = 7 ms)
2023-11-03 17:56:25.28 spid64      Parallel redo is shutdown for database 'testIFI' with worker pool size [1].

2023-11-03 18:02:37.12 Server      Database Instant File Initialization: enabled. For security and performance considerations see the topic 'Database Instant File Initialization' in SQL Server Books Online. This is an informational message only. No user action is required.
2023-11-03 18:04:43.74 spid63      Zeroing C:\tmp\testIFI2_log.ldf from page 0 to 2621440 (0x0 to 0x500000000)
2023-11-03 18:06:14.82 spid63      Zeroing completed on C:\tmp\testIFI2_log.ldf (elapsed = 91083 ms)
2023-11-03 18:06:14.90 spid63      Starting up database 'testIFI2'.
2023-11-03 18:06:14.94 spid63      Parallel redo is started for database 'testIFI2' with worker pool size [1].
2023-11-03 18:06:14.94 spid63      FixupLogTail(progress) zeroing 2 from 0x5000 to 0x6000.
2023-11-03 18:06:14.94 spid63      Zeroing C:\tmp\testIFI2_log.ldf from page 3 to 483 (0x6000 to 0x3c6000)
2023-11-03 18:06:14.95 spid63      Zeroing completed on C:\tmp\testIFI2_log.ldf (elapsed = 8 ms)
2023-11-03 18:06:14.96 spid63      Parallel redo is shutdown for database 'testIFI2' with worker pool size [1].

從上述的結果,你就可以看到,當 Instant File Initialization 啟用時,資料頁面 (Data Page) 是完全不作初始化的動作 (zero),如同上述的說明,最後仍提醒在啟用此功能其實是真的可以大幅減少相關擴展的動作,但其相對的安全性,只能說可能要依不同的行業別在進行評估,如金融業等,當然存放資料的不同,可能也是要考慮,最後也希望此篇可以幫助到大家。

2022年4月6日 星期三

SQL Server - 如何設置單向式合併式複寫

 SQL Server - Replication 複寫是一個在很早的版本就已存在的技術,由於其特性,所以其實有許多的使用者使用,基本上四種常見的複寫上有何差異我就不在特別的介紹,因為已有許多的文章進行說明與比較,而在上一篇文章中,我介紹如何在 AWS RDS for SQL Server 與地端的 SQL Server 進行合併式複寫,這一篇我就再來進一步的介紹如果強制設定單向式的合併式複寫。

優點:

一般複寫在維護上,最怕的就是遇到衝突或是複寫過慢等問題,由於在交易式複寫 (Transactional replication) 與點對點式複寫 (Peer-to-peer replication) 的部份,一遇到衝突,絕大部份需要透過重新建立的方式進行,所以當業務上的需求只需要將資料複寫至遠端時,設定設定成單向式複寫,即可保證目的端的資料不會被變動到。

前一篇設定參考:

如何透過Merge Replication 複寫機制,同步 EC2 與 AWS RDS for SQL Server 的資料庫https://caryhsu.blogspot.com/2022/03/merge-replication-ec2-aws-rds-for-sql.html

詳細的設定方式,可能參考上述文章的介紹,但在加入表格 (Articles) 時,可以再進一步的設定即可,所以我就直接說重點的部份。

1. 先選擇好你要複寫的表格後,然後再點選右上角的 [Article Properties] -> [Properties for All Table Articles].


2. 開啟設定後,您會看到 [Synchronization direction] 的部份,預設為 Bidrectional ,這時可以開啟此設定,你會看到有三個選項。

  • Bidirectional: 雙向式復寫,這也是預設值。
  • Download to Subscriber, prohibit Subscriber changes: 只允許發行端可進行修改,而且當訂閱端進行資料變更時,會發生錯誤訊息,並且不允許進行變更,另外也不會將訂閱端的資料回寫回發行端。
  • Download to Subscriber, allow Subscriber changes: 允許發行端與訂閱端皆可進行修改,但並不會將訂閱端的資料回寫回發行端,而且發行端的數據,也會覆蓋到訂閱端。

此處我們建議可以設定第2項與第3的部份,二者的差異在於,當如果設定為 [Download to Subscriber, prohibit Subscriber changes] 時,如果你在訂閱端進行資料的修改時,就會發生下列的錯誤訊息。

錯誤訊息:
No row was updated.

The data in row 1 was not committed.
Error Source: .Net SqlClient Data Provider.
Error Message: Table '[Person].[Address]' into which you are trying to insert, update, or delete data has been marked as read-only, Only the merge process can perform these operations.



另外如果在已設定好的機器上,需要進行上述的修改時,也是一樣可以的,只是最後在修改後,需要再進行重建快照的動作後即可。