資料列版本控制資源的使用方式

資料列版本控制架構支援 SQL Server 中提供的下列功能:

  • 觸發程序

  • Multiple Active Result Set (MARS)

  • 線上檢索索引

資料列版本控制架構也支援下列資料列版本控制式的交易隔離等級 (預設不會啟用):

  • 當 READ_COMMITTED_SNAPSHOT 資料庫選項是 ON 時,READ_COMMITTED 交易會使用資料列版本控制來提供陳述式層級讀取一致性。

  • 當 ALLOW_SNAPSHOT_ISOLATION 資料庫選項是 ON 時,SNAPSHOT 交易會使用資料列版本控制來提供交易層級讀取一致性。

資料列版本控制式的隔離等級因為不需對讀取作業使用共用鎖定,因而減少交易所取得的鎖定數。如此可減少用來管理鎖定的資源,進而增加系統效能。減少交易被其他交易所取得的鎖定封鎖的次數,也可以增加效能。

資料列版本控制式的隔離等級會增加資料修改所需的資源。啟用這些選項會使資料庫的所有資料修改建立版本。即使沒有使用資料列版本控制式的隔離之使用中交易,也會將修改前的資料副本儲存在 tempdb 中。修改後的資料包括 tempdb 所儲存的版本化資料的指標。若為大型物件,則所變更的物件只有一部分會複製到 tempdb 中。

tempdb 使用的空間

對於 Database Engine 的每一個執行個體,tempdb 必須有足夠空間來保存該執行個體中每一個資料庫所產生的資料列版本。資料庫管理員必須確定 tempdb 有很大的空間可支援版本存放區。tempdb 有兩個版本存放區:

  • 線上索引組建版本存放區會用於所有資料庫的線上索引組建。

  • 一般版本存放區,用於所有資料庫的所有其他資料修改作業。

資料列版本儲存的時間必須夠久,讓使用中交易可以存取它。每隔一分鐘,背景執行緒就會移除不再需要的資料列版本,並釋放 tempdb 中的版本空間。長時間執行的交易如果符合下列任何條件,就可以阻止釋放版本存放區的空間。

  • 它使用資料列版本控制式的隔離。

  • 它使用觸發程序、MARS 或線上索引組建作業。

  • 它產生資料列版本。

[!附註]

在交易內叫用觸發程序時,會維護觸發程序建立的資料列版本,直到交易結束為止,即使在觸發程序完成之後不再需要資料列版本也一樣。這也適用於使用資料列版本控制的讀取認可交易。以此交易類型而言,只有在交易中的每一個陳述式才需要資料庫的交易一致檢視。這表示當交易中的陳述式完成之後,就不再需要為該陳述式建立的資料列版本。不過,仍會維護交易中每一個陳述式所建立的資料列版本,直到交易完成為止。

當 tempdb 空間不夠時,Database Engine 會強制版本存放區壓縮。在壓縮處理期間,執行最久但尚未產生資料列版本的交易會標示為犧牲者。在錯誤記錄檔中會針對每一筆犧牲者交易產生訊息 3967。如果交易已標示為犧牲者,它就不能再讀取版本存放區中的資料列版本。當它嘗試讀取資料列版本時,會產生訊息 3966 而且會回復交易。如果壓縮處理成功,tempdb 中的空間就會變成可用。否則,tempdb 的空間會不足,而且會發生下列情況:

  • 寫入作業繼續執行,但不產生版本。在錯誤記錄檔中會出現資訊訊息 (3959),但寫入資料的交易不受影響。

  • 交易嘗試存取的資料列版本若因為 tempdb 完全回復而未產生,則交易會終止,並出現錯誤 3958。

資料列使用的空間

每個資料庫的資料列在資料列結尾可使用最多 14 個位元組,以存放資料列版本控制資訊。資料列版本控制資訊包含認可版本之交易的交易序號,以及版本化資料列的指標。這 14 個位元組會在第一次修改資料列或插入新的資料列時,而且符合下列任一情況時加入:

  • READ_COMMITTED_SNAPSHOT 或 ALLOW_SNAPSHOT_ISOLATION 選項為 ON。

  • 資料表有觸發程序。

  • 使用 Multiple Active Result Set (MARS)。

  • 目前正在資料表執行線上索引組建作業。

在下列這些情況下,第一次修改資料列時會從資料庫中移除這 14 個位元組:

  • READ_COMMITTED_SNAPSHOT 和 ALLOW_SNAPSHOT_ISOLATION 選項為 OFF。

  • 觸發程序已不在資料表上。

  • 不使用 MARS。

  • 目前沒有執行中的線上索引建立作業。

如果您使用任何資料列版本控制功能,您可能需要配置額外的磁碟空間給資料庫,以容納每個資料庫資料列的 14 個位元組。如果目前頁面沒有足夠的可用空間,則加入資料列版本控制資訊會造成索引頁面分割或需要配置新的資料頁。例如,如果平均資料列長度是 100 個位元組,則額外的 14 個位元組會造成現有資料表成長高達 14%。

降低填滿因數可能有助於防止或減少索引頁片段。若要檢視資料表或檢視表之資料與索引的片段資訊,您可以使用 DBCC SHOWCONTIG

大型物件使用的空間

SQL Server Database Engine 支援 6 種資料類型,可保留長度多達 2 GB 的大型字串:nvarchar(max)、varchar(max)、varbinary(max)、ntext、text 和 image。使用這些資料類型儲存的大型字串是儲存在一系列資料片段中,而這些片段是連結到資料列。資料列版本控制資訊是儲存在用來儲存這些大型字串的每一個片段中。資料片段是專供資料表中大型物件使用的頁面集合。

當新的大型值加入至資料庫時,會使用每個片段最多 8040 個位元組的資料來配置它們。舊版的 Database Engine 中,每個片段儲存最多 8080 個位元組的 ntext、text 或 image 資料。

當資料庫從舊版的 SQL Server 升級到 SQL Server 時,並不會更新現有的 ntext、text 和 image 大型物件 (LOB) 資料來提供存放資料列版本控制資訊的空間。不過,第一次修改 LOB 資料時,它會動態升級,以啟用版本控制資訊的儲存。即使未產生資料列版本也會發生此情況。當 LOB 資料升級之後,每個片段儲存的最大位元組數會從 8080 個位元組降到 8040 個位元組。升級程序相當於刪除 LOB 值及重新插入相同值。即使只修改一個位元組,也會升級 LOB 資料。每一個 ntext、text 或 image 資料行只有一次作業,但每一個作業可產生大量頁面配置和 I/O 活動,視 LOB 資料大小而定。如果有完整記錄各項修改,則它也可能產生大量記錄活動。如果資料庫復原模式未設為 FULL,則會為 WRITETEXT 和 UPDATETEXT 作業做最少的記錄。

舊版的 SQL Server 並沒有提供 nvarchar(max)、varchar(max) 和 varbinary(max) 資料類型。因此,它們沒有升級問題。

應該配置足夠的磁碟空間來配合這項需求。

監視資料列版本控制和版本存放區

為了效能和問題而監視資料列版本控制、版本存放區和快照集隔離程序,SQL Server 以動態管理檢視 (DMV) 的形式提供工具,以及在 Windows 系統監視器中提供效能計數器。

DMV

下列 DMV 提供關於 tempdb 和版本存放區的目前系統狀態,以及使用資料版本控制的交易之資訊。

sys.dm_db_file_space_usage。傳回資料庫中每個檔案的空間使用量資訊。如需詳細資訊,請參閱<sys.dm_db_file_space_usage (Transact-SQL)>。

sys.dm_db_session_space_usage。由資料庫的工作階段傳回頁面配置和取消配置活動。如需詳細資訊,請參閱<sys.dm_db_session_space_usage (Transact-SQL)>。

sys.dm_db_task_space_usage。傳回資料庫工作的頁面配置及取消配置活動。如需詳細資訊,請參閱<sys.dm_db_task_space_usage (Transact-SQL)>。

sys.dm_tran_top_version_generators。針對產生版本存放區中大部分版本的物件,傳回一份虛擬資料表。它按 database_id 和 rowset_id 來分組前 256 個彙總記錄長度。使用此函數可尋找版本存放區的最大取用者。如需詳細資訊,請參閱<sys.dm_tran_top_version_generators (Transact-SQL)>。

sys.dm_tran_version_store。傳回虛擬資料表來顯示一般版本存放區中的所有版本記錄。如需詳細資訊,請參閱<sys.dm_tran_version_store (Transact-SQL)>。

[!附註]

sys.dm_tran_top_version_generators 和 sys.dm_tran_version_store 可能是執行代價很高的函數,因為兩者會查詢有可能是非常龐大的整個版本存放區。

sys.dm_tran_active_snapshot_database_transactions。在使用資料列版本控制的 SQL Server 執行個體內,傳回所有資料庫的所有使用中交易的虛擬資料表。系統交易不會出現在這個 DMV 中。如需詳細資訊,請參閱<sys.dm_tran_active_snapshot_database_transactions (Transact-SQL)>。

sys.dm_tran_transactions_snapshot。傳回虛擬資料表,以顯示每一筆交易所產生的快照集。快照集包含使用了資料列版本控制之使用中交易的序號。如需詳細資訊,請參閱<sys.dm_tran_transactions_snapshot (Transact-SQL)>。

sys.dm_tran_current_transaction。傳回單一資料列,顯示目前工作階段中交易的資料列版本控制相關之狀態資訊。如需詳細資訊,請參閱<sys.dm_tran_current_transaction (Transact-SQL)>。

sys.dm_tran_current_snapshot。傳回虛擬資料表,以顯示目前快照集隔離交易啟動時的所有使用中交易。如果目前交易是使用快照集隔離,則此函數不傳回資料列。sys.dm_tran_current_snapshot 類似 sys.dm_tran_transactions_snapshot,只不過它只傳回目前快照集的使用中交易。如需詳細資訊,請參閱<sys.dm_tran_current_snapshot (Transact-SQL)>。

效能計數器

SQL Server 效能計數器可提供受到 SQL Server 程序影響的系統效能相關資訊。下列效能計數器會監視 tempdb、版本存放區以及使用資料列版本控制的交易。效能計數器包含在 SQLServer:Transactions 效能物件中。

Free Space in tempdb (KB)。監視 tempdb 資料庫的可用空間量,以 KB 為單位。tempdb 要有足夠的可用空間,才能處理支援快照集隔離的版本存放區。

下列公式提供版本存放區大小的概估。若為長時間執行的交易,則監視產生速率和清除速率以評估版本存放區的大小上限,可能會有幫助。

[一般版本存放區的大小] = 2 * [每分鐘產生的版本存放區資料] * [交易的最長執行時間 (分鐘數)]

交易的最長執行時間不應包括線上索引組建。由於這些作業在非常大的資料表上會花很長的時間,線上索引組建會使用不同的版本存放區。線上索引組建版本存放區的近似大小,等於啟動線上索引組建時資料表中修改的資料量,包括所有索引。

Version Store Size (KB)。監視所有版本存放區的大小,以 KB 為單位。此資訊有助於決定版本存放區的 tempdb 資料庫所需要的空間量。持續監視這個計數器一段時間,可對 tempdb 所需的其他空間提供有用的評估。

Version Generation rate (KB/s)。監視所有版本存放區的版本產生速率 (以每秒 KB 數為單位)。

Version Cleanup rate (KB/s)。監視所有版本存放區的版本清除速率 (以每秒 KB 數為單位)。

[!附註]

Version Generation rate (KB/s) 和 Version Cleanup rate (KB/s) 的資訊可用來預測 tempdb 的空間需求。

Version Store unit count。監視版本存放區單元的計數。

Version Store unit creation。監視自執行個體啟動之後,為了儲存資料列版本而建立之版本存放區單元的總數。

Version Store unit truncation。監視自執行個體啟動之後,被截斷之版本存放區單元的總數。當 SQL Server 判斷執行使用中交易時不再需要版本存放區單元中所儲存的任何版本資料列時,就會截斷版本存放區單元。

Update conflict ratio。監視有更新衝突的更新快照集交易與更新快照集交易總數的比例。

Longest Transaction Running Time。監視使用資料列版本控制的任何交易的最長執行時間,以秒數為單位。這可用來判斷是否有任何交易執行的時間量不合理。

Transactions。監視使用中交易的總數。這不包括系統交易。

Snapshot Transactions。監視使用中快照集交易的總數。

Update Snapshot Transactions。監視執行更新作業的使用中快照集交易的總數。

NonSnapshot Version Transactions。監視產生版本記錄的使用中非快照集交易的總數。

[!附註]

Update Snapshot Transactions 和 NonSnapshot Version Transactions 的總和代表參與版本產生的交易總數。Snapshot Transactions 和 Update Snapshot Transactions 的差異可報告唯讀快照集交易的數目。