Sintomi
Quando si confrontano le SYSCOMMITTABLE in memoria e il file su disco sys.syscommittab in Microsoft SQL Server, si possono vedere le righe di chiave duplicate. Questi valori duplicati possono causare operazioni di backup e del punto di arresto l'esito negativo.
"Impossibile inserire la riga di chiave duplicata nell'oggetto 'sys.syscommittab' con indice univoco 'si_xdes_id'. Il valore della chiave duplicato è (KeyValue).
Errore: 3999, verrà restituito, gravità: 17, stato: 1.
Impossibile svuotare la tabella commit su disco in dbid ID errore 2601. Controllare il log degli errori per ulteriori informazioni".
Causa
Questo problema si verifica a causa di un problema noto di rilevamento delle modifiche di SQL Server.
Risoluzione
Per risolvere i fattori che causano le chiavi duplicate, applicare una delle seguenti correzioni, come appropriato alla situazione: FIX: un'operazione di backup su un database di SQL Server 2008 o SQL Server 2008 R2 ha esito negativo se si abilita rilevamento delle modifiche in questo databasehttp://support.microsoft.com/kb/2522893FIX: Backup non riesce in SQL Server 2008 R2, SQL Server 2008 o SQL Server 2012 se si abilita rilevamento delle modifiche in http://support.microsoft.com/kb/2603910il database correzione: operazione di Backup non riesce in un 2008 di SQL Server , SQL Server 2008 R2 o dopo aver attivato il rilevamento delle http://support.microsoft.com/kb/2682488, anche se queste correzioni righe di chiave duplicate non potrà continuare a vengono visualizzati, essi non vengono rimossi automaticamente le righe duplicate modifiche del database di SQL Server 2012. Senza rimuovere le righe duplicate, il database interessato non può completare i checkpoint del database e backup potrebbero non riuscire. Per rimuovere le righe duplicate, utilizzare uno dei metodi descritti di seguito.
Metodo 1: Disattivare e attivare il rilevamento delle modifiche
-
Disattivare le tabelle interessate e database di rilevamento delle modifiche.
-
Emettere un CHECKPOINT manuale del database.
-
Attiva sul database interessato e tabelle di rilevamento delle modifiche.
Per ulteriori informazioni sul rilevamento delle modifiche, vedere attivare e disattivare il rilevamento delle modifiche. Per informazioni su come eseguire un'istruzione CHECKPOINT manuale, vedere CHECKPOINT (Transact-SQL)
Metodo 2: Eliminare manualmente le righe duplicate
-
Copiare lo script Transact-SQL alla fine della sezione "Risoluzione" in un editor di testo.
-
Individuare il segnaposto < AFFECTED_DB > nello script e sostituirlo con il nome del database interessato.
-
Salvare lo script modificato sul disco rigido come file con estensione SQL. Per esempio:
C:\temp\remove_duplicates.sql
Se si esegue SQL Server 2014, è necessario concedere il controllo completo del SID al servizio per i file mssqlsystemresource.ldf e mssqlsystemresource.mdf. A tale scopo, attenersi alla seguente procedura:
-
Passare alla directory Binn che corrisponde al tuo ID di istanza. Per esempio:
C:\Program Files\Microsoft SQL Server \MSSQL\Binn < ID istanza >
-
Aprire la finestra delle proprietà mssqlsystemresource.ldf e mssqlsystemresource.mdf e quindi fare clic sulla scheda protezione .
-
Individuare il SID al servizio di servizio di SQL Server e notare le autorizzazioni predefinite:
* Lettura ed esecuzione
*Read
-
Il servizio SQL Server di concedere il controllo completo di SID di servizio e quindi chiudere le finestre di dialogo autorizzazioni.
-
Avviare SQL Server in modalità utente singolo. Per ulteriori informazioni, vedere Avvio di SQL Server in modalità utente singolo.
-
Utilizzare una riga di comando sqlcmd per connettersi a SQL Server in amministratore connessione dedicata (DAC). Per esempio:
SQLCMD -S PRODSERV1\MSSQLSERVER - A -E -i c:\temp\remove_duplicates.sqlQuindi, eseguire lo script Transact-SQL modificato.
-
Avviare SQL Server in modalità multiutente e verificare che operazioni di backup e CHECKPOINT nel database interessato completano. Se è stato utilizzato il passaggio 4, ripristinare le autorizzazioni per i valori predefiniti.
Script Transact-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