徵狀

比較時於記憶體 SYSCOMMITTABLE 和 Microsoft SQL Server 中的磁碟上的 sys.syscommittab 檔案,您可能會看到重複的索引鍵資料列。這些重複的值可能會造成備份和檢查點作業失敗。

「 無法插入重複的索引鍵資料列,在物件 'sys.syscommittab' 'si_xdes_id' 的唯一索引。重複的索引鍵值是 (KeyValue)。

錯誤: 3999,高的嚴重性等級: 17,狀態: 1。

無法排清到磁碟中因為錯誤 2601 dbid DatabaseID的認可資料表。檢查錯誤記錄檔,如需詳細資訊 >。

原因

之所以發生這個問題,是因為 SQL Server 變更追蹤已知的問題。

解決方案

若要解決導致重複的索引鍵的因素,將套用下列修正程式中,視您的情況: 修正: 在 SQL Server 2008年或 SQL Server 2008 R2 的資料庫上的備份作業失敗時,如果您啟用這個資料庫http://support.microsoft.com/kb/2522893修正程式的歷程: 備份失敗 SQL Server 2008年、 SQL Server 2008 R2 或 SQL Server 2012年中,如果您啟用變更追蹤上資料庫http://support.microsoft.com/kb/2603910修正程式: SQL Server 2008年中的備份作業失敗SQL Server 2008 R2 或啟用變更追蹤http://support.microsoft.com/kb/2682488,雖然這些修正程式會導致重複的索引鍵資料列無法繼續出現,它們並不會自動移除重複的資料列後,SQL Server 2012年資料庫。而不要移除重複的資料列受影響的資料庫不能完成資料庫檢查點,且備份可能會失敗。若要移除重複的資料列,請使用下列方法之一。

方法 1: 停用及啟用變更追蹤

  1. 停用追蹤受影響的資料表與資料庫的變更。

  2. 發出手動進行資料庫檢查點。

  3. 啟用 [追蹤] 將受影響的資料庫和資料表的變更。

如需有關變更追蹤的詳細資訊,請參閱啟用和停用變更追蹤。如需有關如何發出手動檢查點的資訊,請參閱檢查點 (考慮改用 SQL)

方法 2: 以手動方式刪除重複的資料列

  1. 將在 < 解決方案=""> 一節結尾處的考慮改用 SQL 指令碼複製到文字編輯器。

  2. 找出的 < AFFECTED_DB > 版面配置區中的指令碼,並取代受影響的資料庫名稱。

  3. 將儲存修改過的指令碼到您的硬碟為.sql 檔案。例如:

    C:\temp\remove_duplicates.sql

如果您執行 SQL Server 2014年,您必須授與每個服務的 SID 完全控制的 mssqlsystemresource.ldf 和 mssqlsystemresource.mdf 的檔案。若要這麼做,請依照下列步驟執行:

  1. 巡覽至 Binn 目錄對應到您的執行個體識別碼。例如:

    C:\Program 必要 SQL Server\ < 執行個體識別碼 > \MSSQL\Binn

  2. 開啟 mssqlsystemresource.ldf 和 mssqlsystemresource.mdf 的屬性,然後按一下 [安全性] 索引標籤。

  3. 找出 SQL Server 服務每個服務 SID,並請注意預設權限:

    * 讀取 & 執行

    *Read

  4. 授與 SQL Server 服務每個服務 SID 完全控制],,然後關閉 [權限] 對話方塊。

  5. 在單一使用者模式中啟動 SQL Server。如需詳細資訊,請參閱在單一使用者模式中啟動 SQL Server

  6. 連線到 SQL Server 專用的系統管理員連線 (DAC) 下使用sqlcmd命令列。例如:

    sqlcmd-S PRODSERV1\MSSQLSERVER-A-E-i c:\temp\remove_duplicates.sql然後,執行修改過的考慮改用 SQL 指令碼。

  7. 在多使用者模式中,啟動 SQL Server,然後確認備份與對受影響的資料庫的檢查點作業順利完成。如果使用步驟 4,將還原成預設值的權限。

交易 SQL 指令碼

--Create a temporary database to store the necessary rows required to remove the duplicate dataif exists(select 1 from sys.databases where name = 'dbChangeTrackingMetadata')begindrop database dbChangeTrackingMetadataendgocreate database dbChangeTrackingMetadatago --Table to store the contents of the SYSCOMMITTABLEuse dbChangeTrackingMetadatagocreate table dbo.t_SYSCOMMITTABLE (commit_ts bigint,xdes_id bigint,commit_lbn bigint,commit_csn bigint,commit_time datetime)go --Table to store the duplicate rows to be removed from the sys.syscommittab tablecreate table dbo.t_syscommittab (commit_ts bigint,xdes_id bigint,commit_lbn bigint,commit_csn bigint,commit_time datetime,dbfragid int)go --Enable the usage of OPENROWSETexec sys.sp_setbuildresource 1go --Change <AFFECTED_DB> to the database that contains the duplicate valuesUSE <AFFECTED DB>godeclare @rowcount bigintSET @rowcount = 0 --Copy all rows from the SYSCOMMITTABLE into the temporary databaseinsert into dbChangeTrackingMetadata.dbo.t_SYSCOMMITTABLESELECT commit_ts, xdes_id, commit_lbn, commit_csn, commit_timeFROM OpenRowset (table SYSCOMMITTABLE, db_id (), 0, 0) --Save the duplicate values into the temporary databaseinsert into dbChangeTrackingMetadata.dbo.t_syscommittabselect ondisk_ct.* from sys.syscommittab as ondisk_ctjoin dbChangeTrackingMetadata.dbo.t_SYSCOMMITTABLE as inmem_cton ondisk_ct.xdes_id = inmem_ct.xdes_id --Delete the duplicate valuesdelete from sys.syscommittabwhere xdes_id in ( select xdes_id from dbChangeTrackingMetadata.dbo.t_syscommittab )set @rowcount = @@rowcountif (@rowcount > 0)beginprint ''print 'DELETED '+CAST(@rowcount as NVARCHAR(10))+' rows from sys.syscommittab that were also stored in SYSCOMMITTABLE'print ''endelsebeginprint ''print 'Failed to DELETE DUP rows from sys.syscommittab'print ''endexec sys.sp_setbuildresource 0go 

Need more help?

Expand your skills
Explore Training
Get new features first
Join Microsoft Insiders

Was this information helpful?

How satisfied are you with the translation quality?
What affected your experience?

Thank you for your feedback!

×