T-SQL 更改数据捕获日志清理

问题描述 投票:0回答:3

我已在 SQL Server 2008 数据库中的几个表上启用了 CDC。我想更改可以保留更改历史记录的天数。

我读过,默认情况下更改日志会保留 3 天,然后由 sys.sp_cdc_cleanup_change_table 存储过程删除。

有谁知道如何更改此默认值,以便我可以保留日志更长时间。

谢谢

sql-server-2008 t-sql
3个回答
3
投票

您需要更新数据库的 cdc_jobs.retention 字段。在至少为 CDC 启用一个表之前,cdc_jobs 表中的记录不会存在。

-- modify msdb.dbo.cdc_jobs.retention value (in minutes) to be the length of time to keep change-tracked data
update
    j
set
    [retention] = 3679200 -- 7 years
from
    sys.databases d
inner join
    msdb.dbo.cdc_jobs j
        on j.database_id = d.database_id
        and j.job_type = 'cleanup'
        and d.name = '<Database Name, sysname, DatabaseName>';

<Database Name, sysname, DatabaseName>
替换为您的数据库名称。


2
投票

两种替代解决方案:

  1. 放弃清理工作:

    EXEC sys.sp_cdc_drop_job @job_type = N'cleanup';
    
  2. 通过 sp 更改工作:

    EXEC sys.sp_cdc_change_job 
    @job_type = N'cleanup',
    @retention = 2880;
    

保留时间以分钟为单位,最长 52494800(100 年)。但是,如果您放弃作业,则数据永远不会被清理,如果有数据需要清理,作业甚至不会查找。如果想无限期地保留数据,我宁愿放弃这份工作。


0
投票

顺便说一句:如果您配置了 AlwaysOn 可用性组,则必须记住在故障转移后更新新主节点上的 CDC 配置! 在将保留期更新为比默认 3 天更长的值后,我们经历了惨痛的教训,在故障转移后我们丢失了这些更改!

或者,您可以通过比较 PRIMARY/SECONDARY 配置值,然后直接在辅助服务器上更新 msdb.dbo.cdc_jobs 来匹配,从而主动更新 SECONDARY 服务器。我不知道 Microsoft 是否正式支持这一点,但他们也不阻止直接更新 msdb 表。

以下是一个示例脚本,您可以在 AlwaysON 组中的副本上进行安排。它将检查主服务器上的当前配置并将更改同步到辅助服务器...


SET NOCOUNT ON  

--We assume if this is the primary for even ONE database, then don't run 
IF NOT EXISTS(
SELECT name,is_cdc_enabled,
sys.fn_hadr_is_primary_replica ( name) as IsPrimary
FROM sys.databases 
WHERE is_cdc_enabled=1
AND sys.fn_hadr_is_primary_replica ( name) =1
)
BEGIN

    DECLARE @Listener sysname  
    DECLARE @PrimaryConnectString VARCHAR(1000)  
    DECLARE @OPENROWSETString VARCHAR(4000)


    --We just need to get ONE ListenerName to connect to the PRIMARY.
    SET @Listener=(SELECT TOP 1 dns_name from sys.availability_group_listeners GL  
      join sys.availability_group_listener_ip_addresses LIP  
      on GL.listener_id = LIP.listener_id)  
    SET @PrimaryConnectString='Server='+@Listener+';Database=msdb;TrustServerCertificate=Yes;Trusted_Connection=Yes;MultiSubnetFailover=Yes;'

    SELECT @PrimaryConnectString

    SET @OPENROWSETString='
    SELECT *
    FROM OPENROWSET(
        ''SQLNCLI'',
        '''+@PrimaryConnectString+''',
        ''IF EXISTS (SELECT 1 FROM msdb.dbo.cdc_jobs) SELECT 
    @@Servername as ServerName,
    sd.name as DBName,
    cdc.database_id,
    cdc.job_type,
    cdc.job_id,
    cdc.maxtrans,
    cdc.maxscans,
    cdc.continuous,
    cdc.pollinginterval,
    cdc.retention,
    cdc.threshold
    FROM msdb.dbo.cdc_jobs cdc
    JOIN sys.databases sd
    ON cdc.database_id=sd.database_id''
    )'

  

    DROP TABLE IF EXISTS #RemoteConfig
    CREATE TABLE #RemoteConfig (
    ServerName varchar(64),
    DBName varchar(64),
    database_id int,
    job_type varchar(12),
    job_id uniqueidentifier,
    maxtrans int,
    maxscans int,
    continuous bit,
    pollinginterval int,
    retention int,
    threshold int
    )

    INSERT INTO #RemoteConfig
    EXEC (@OPENROWSETString);

    DROP TABLE IF EXISTS #LocalConfig
    IF EXISTS (SELECT 1 FROM msdb.dbo.cdc_jobs) 
        SELECT  
        @@Servername as ServerName,
        sd.name as DBName,
        cdc.database_id,
        cdc.job_type,
        cdc.job_id,
        cdc.maxtrans,
        cdc.maxscans,
        cdc.continuous,
        cdc.pollinginterval,
        cdc.retention,
        cdc.threshold
        INTO #LocalConfig 
        FROM msdb.dbo.cdc_jobs cdc
        JOIN sys.databases sd
        ON cdc.database_id=sd.database_id

    --DEBUG
    SELECT 'PRIMARY'as Role,* FROM #RemoteConfig
    SELECT 'SECONDARY' as [Role],* FROM #LocalConfig

    --Will update if there are any unmatching column values for each job type and db
    UPDATE l   
    SET l.maxtrans=r.maxtrans,
        l.maxscans=r.maxscans,
        l.continuous=r.continuous,
        l.pollinginterval=r.pollinginterval,
        l.retention=r.retention,
        l.threshold=r.threshold
    FROM msdb.dbo.cdc_jobs as l
    JOIN #RemoteConfig r
        ON db_name(l.database_id) = r.DBname
        AND l.job_type = r.job_type
    WHERE
        r.maxtrans <> l.maxtrans OR
        r.maxscans <> l.maxscans OR
        r.continuous <> l.continuous OR
        r.pollinginterval <> l.pollinginterval OR
        r.retention <> l.retention OR
        r.threshold <> l.threshold

    IF @@ROWCOUNT > 0 PRINT '***CHANGES SYNCHED***' ELSE PRINT '***NO CHANGES***'

    SELECT db_name(msdb.dbo.cdc_jobs.database_id) as DBName, * FROM  msdb.dbo.cdc_jobs

END
ELSE 
BEGIN 
    PRINT '***PRIMARY REPLICA, SKIPPING CONFIG SYNC***'
    SELECT db_name(msdb.dbo.cdc_jobs.database_id) as DBName, * FROM  msdb.dbo.cdc_jobs
END
© www.soinside.com 2019 - 2024. All rights reserved.