您的位置:新葡亰496net > 网络数据库 > 新葡亰496net:的由来深入分析和消除办法,监察

新葡亰496net:的由来深入分析和消除办法,监察

发布时间:2019-12-10 14:07编辑:网络数据库浏览(166)

     

    复制和CDC 都是使用logreader来从日志中读取数据的变更,然后写入到分发库(复制)或变更表中。

    一.本文所涉及的内容(Contents)

    1. 本文所涉及的内容(Contents)
    2. 背景(Contexts)
    3. 实现过程(Realization)
    4. 补充说明(Addon)
    5. 参考文献(References)

    本文出处: 

    1> 单独创建复制发布

    二.背景(Contexts)

      在SQL Server 2008版本之前,对表数据库的变更监控,我们通常使用DML触发器进行监控,把DML操作中的INSERT/UPDATE/DELETE数据记录下来,但是触发器的维护比较困难;

      当SQL Server 2008新功能:变更数据捕获(Change Data Capture,即CDC)出来之后,我发现这正是我想要的,因为我之前使用DML触发器实现的时候也是把UPDATE操作按照两条记录进行记录的,共同的缺点都是在用户修改了表结构后,CDC不会自动同步到记录中,不过CDC也有DDL的监控可以补充这个缺陷;CDC的优点就是以异步进程读取事务日志进行捕获数据变更的。

     

    在该情况下,会在分发服务器上创建日志读取代理作业(ServerName_DBName_logreaderID)

    三.实现过程(Realization)

    (一) 创建一个测试数据库;

    新葡亰496net 1;)

    /******* Step1:创建示例数据库*******/
    USE master
    GO
    IF EXISTS(SELECT name FROM sys.databases WHERE name = 'CDC_DB')
    DROP DATABASE CDC_DB
    GO
    CREATE DATABASE CDC_DB
    GO
    

    新葡亰496net 2;)

     

    (二) 在开启数据库的CDC之前先查询一下状态,is_cdc_enabled值为0表示没有开启,1表示开启,当为数据库[CDC_DB]启用了CDC之后,在CDC_DB系统表中会出现下图Figure2所示的6个表;

    新葡亰496net 3;)

    /******* Step2:开启数据库CDC *******/
    --查看数据库是否启用CDC
    SELECT name,is_cdc_enabled FROM sys.databases WHERE name = 'CDC_DB'
    
    --启用数据库CDC
    USE CDC_DB
    GO
    EXECUTE sys.sp_cdc_enable_db;
    GO
    
    --检查启用是否成功
    SELECT is_cdc_enabled,CASE WHEN is_cdc_enabled=0 THEN 'CDC功能禁用' ELSE 'CDC功能启用' END 描述
    FROM sys.databases
    WHERE NAME = 'CDC_DB'
    

    新葡亰496net 4;)

    新葡亰496net 5

    (Figure1:数据库CDC状态)

    新葡亰496net 6

    (Figure2:启用数据库CDC创建的系统表)

    新葡亰496net 7

    (Figure3:数据库CDC状态)

    新葡亰496net 8

    (Figure4:添加新用户和架构)

    开启数据库的CDC之后,分别在用户和架构上创建新的用户cdc,新的架构cdc;

     

    (三) 创建一个测试表,对表行变更启用捕获,为表[Department]启用CDC,首先会在系统表中创建[cdc].[dbo_Department_CT],会在Agent中创建两个作业,cdc.CDC_DB_capture和cdc.CDC_DB_cleanup,启用表变更捕获需要开启SQL Server Agent服务,不然会报错。每对一个表启用捕获就会生成一个向对应的记录表。

    新葡亰496net 9;)

    /******* Step3:对表启用变更捕获*******/
    --创建测试表
    USE CDC_DB
    GO
    CREATE TABLE [dbo].[Department](
        [DepartmentID] [smallint] IDENTITY(1,1) NOT NULL,
        [Name] [nvarchar](200) NULL,
        [GroupName] [nvarchar](50) NOT NULL,
        [ModifiedDate] [datetime] NOT NULL,
        [AddName] [nvarchar](120) NULL,
     CONSTRAINT [PK_Department_DepartmentID] PRIMARY KEY CLUSTERED 
    (
        [DepartmentID] ASC
    ) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    
    --对表启用捕获
    EXEC sys.sp_cdc_enable_table 
        @source_schema= 'dbo',
           @source_name = 'Department',
           @role_name = N'cdc_Admin',
           @capture_instance = DEFAULT,
           @supports_net_changes = 1,
        @index_name = NULL,
        @captured_column_list = NULL,
        @filegroup_name = DEFAULT
    
    --检查是否成功
    SELECT name, is_tracked_by_cdc ,
        CASE WHEN is_tracked_by_cdc = 0 THEN 'CDC功能禁用' ELSE 'CDC功能启用' END 描述
    FROM sys.tables
    WHERE OBJECT_ID= OBJECT_ID('dbo.Department')
    
    --返回某个表的变更捕获配置信息
    EXEC sys.sp_cdc_help_change_data_capture 'dbo', 'Department'
    

    新葡亰496net 10;)

    新葡亰496net 11

    (Figure5:提示信息)

    新葡亰496net 12

    (Figure6:新增加的系统表)

    新葡亰496net 13

    (Figure7:生成的捕获和清理作业)

    新葡亰496net 14

    (Figure8:表的CDC状态)

    新葡亰496net 15

    (Figure9:多了个数据库角色)

    新葡亰496net 16

    新葡亰496net 17

    (Figure10:sys.sp_cdc_enable_table配置选项)

    上图深色部分的字段值是在执行sys.sp_cdc_enable_table的时候设置的。

     

    (四) 测试插入数据、更新数据、删除数据,执行完这些DML,我们来观察下cdc.dbo_Department_CT帮我们记录些什么?

    新葡亰496net 18;)

    /******* Step4:测试DML变更捕获*******/
    --测试插入数据
    INSERT  INTO dbo.Department(
        Name ,
        GroupName ,
        ModifiedDate
    )VALUES('Marketing','Sales and Marketing',GETDATE())
    
    --测试更新数据
    UPDATE dbo.Department SET Name = 'Marketing Group',ModifiedDate = GETDATE()
    WHERE Name = 'Marketing'
    
    --测试删除数据
    DELETE FROM dbo.Department WHERE Name='Marketing Group'
    
    --查询捕获数据
    SELECT * FROM cdc.dbo_Department_CT
    

    新葡亰496net 19;)

    新葡亰496net 20

    (Figure11:变更记录表)

    对于insert/delete操作,会有对应的一行记录,而对于update,会有两行记录。__$operation列:1 = 删除、2= 插入、3= 更新(旧值)、4= 更新(新值);

     

    (五) 启用CDC之后,你怎么从中获取到数据呢?通过数据我们可以对数据进行恢复;

    新葡亰496net 21;)

    /******* Step6:使用LSN 查看CDC记录*******/
    --http://msdn.microsoft.com/zh-cn/library/bb500137(v=sql.100).aspx
    SELECT sys.fn_cdc_map_time_to_lsn
    ('smallest greater than or equal', '2013-07-24 09:00:30') AS BeginLSN
    
    SELECT sys.fn_cdc_map_time_to_lsn
    ('largest less than or equal', '2013-07-24 23:59:59') AS EndLSN
    
    
    /******* 查看某时间段所有CDC记录*******/
    DECLARE @FromLSN binary(10) =
    sys.fn_cdc_map_time_to_lsn
    ('smallest greater than or equal' , '2013-06-23 09:00:30')
    
    DECLARE @ToLSN binary(10) =
    sys.fn_cdc_map_time_to_lsn
    ('largest less than or equal' , '2013-07-26 23:59:59')
    
    SELECT CASE [__$operation]
    WHEN 1 THEN 'DELETE'
    WHEN 2 THEN 'INSERT'
    WHEN 3 THEN 'Before UPDATE'
    WHEN 4 THEN 'After UPDATE'
    END Operation,[__$operation],[__$update_mask],DepartmentId,Name,GroupName,ModifiedDate,AddName
    FROM [cdc].[fn_cdc_get_all_changes_dbo_Department]
    (@FromLSN, @ToLSN,  N'all update old')
    /*
    all 其中的update,只包含新值
    all update old 包含新值和旧值
    */
    

    新葡亰496net 22;)

    新葡亰496net 23

    (Figure15:通过时间获取LSN更新)

     

    (六) CDC的维护

    新葡亰496net 24;)

    /******* Step5:维护CDC *******/
    --返回所有表的变更捕获配置信息
    EXECUTE sys.sp_cdc_help_change_data_capture;
    
    --返回某个表的变更捕获配置信息
    EXEC sys.sp_cdc_help_change_data_capture 'dbo', 'Department'
    
    --查看对某个表的哪些列做了捕获监控,使用上面返回的capture_instance列值
    EXEC sys.sp_cdc_get_captured_columns
    @capture_instance = 'dbo_Department'
    

    新葡亰496net 25;)

    新葡亰496net 26

    (Figure12:监控表字段信息)

    由于sys.sp_cdc_enable_table 的参数:@captured_column_list = NULL,所以dbo.Department表的所有字段都进行监控了,如果你只关心某些字段,强烈建议在创建捕获的时候设置这个属性;

    新葡亰496net 27;)

    --所有数据库CDC Job信息
    SELECT B.name,A.* FROM msdb.dbo.cdc_jobs AS A
    LEFT JOIN sys.databases AS B
    ON A.database_id = B.database_id
    
    --当前数据库CDC Job信息
    EXEC sp_cdc_help_jobs
    

    新葡亰496net 28;)

    新葡亰496net 29

    (Figure13:数据库作业信息)

    SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为:
    在执行增删改语句(产生事务日志)的过程中提示,The transaction log for database '***' is full due to 'REPLICATION'(数据库“***”的事务日志已满,原因为“REPLICATION”).

    2> 单独使用CDC

    四.补充说明(Addon)

      SQL Server记录数据变更有四种方法:触发器、Output子句、变更数据捕获(Change Data Capture 即CDC)功能、同步更改跟踪。其中后两个为SQL Server 2008所新增。

    CDC功能主要捕获SQLServer指定表的增删改操作;

    CDC除了捕获数据变更之外,还能捕获DDL操作的变化;

    无法对系统数据库和分发数据库启用该功能。且执行者需要用sysadmin角色权限;

    cdc.<capture_instance>_CT   可以看到,这样命名的表,是用于记录源表更改的表。对于insert/delete操作,会有对应的一行记录,而对于update,会有两行记录;

    对于__$start_lsn列:由于更改是来源与数据库的事务日志,所以这里会保存其事务日志的开始序列号(LSN);

    对于__$end_lsn列:

    对于__$seqval列:

    对于__$operation列:1 = 删除、2= 插入、3= 更新(旧值)、4= 更新(新值);

    新葡亰496net:的由来深入分析和消除办法,监察和控制表数据。对于__$update_mask列:

    恢复模式为简单模式一样可以进行CDC;

    虽然能捕获到数据变更,但是没有办法找到是谁更新的?

    能使用这个做回滚嘛?备份的另外一种路径?对表更新不频繁的情况下?

    如果是添加或者删除了某些字段DDL,那么创建的CDC表并没有做更改,那新字段的数据怎么捕获呢?修改字段长度等这些操作同样会一起修改CDC对应的表字段;

    sys.sp_cdc_enable_table 的@role_name参数,是指角色-数据库角色,这个有什么用呢?应用程序角色又有什么用呢?

    cdc.Person_Contact_CT这名字中CT代表什么意思呢?Capture Table?(用户.架构_表_CT)

    SQL Server 自启动了两个job,一个捕获,一个清除,注意清除是默认凌晨2点,清除72小时以上的数据。如果同一数据库的表中CDC已经启用,不会重建job。

    all

    返回指定 LSN 范围内的所有更改。 对于由更新操作导致的更改,此选项只返回在应用更新之后包含新值的行。

    all update old

    返回指定 LSN 范围内的所有更改。 对于由更新操作导致的更改,此选项将返回在更新之前包含列值的行和更新之后包含列值的行。

     

    文章出处:

     

    CDC以及复制的基本原理粗略地讲,对于日志的使用步骤如下:
      1,每当基础表(开启了CDC或者replication的表)产生事务性操作(增删改)之后,对应的事务日志写入日志文件,
      2,此时的日志被状态被标记为Replication,也即处于待复制状态,这个活动状态跟数据库的还原模式无关,即便是简单还原模式,
      3,然后有后台进程来读取这个日志,根据事务日志的内存写入目标表,
        这个目标对于cdc来说是记录数据变化的系统表,
        对于replication来说是写入distribution这个库
      4,步骤3完成之后,事务日志被标记为正常状态,如果是简单还原模式,被后台进程解析过的事务日志被截断,可以重用

    在该情况下,会在当前实例的代理上创建两个作业‘cdc.DBName_capture’(调用sys.sp_MScdc_capture_job来读取日志)和‘cdc.DemoDB3_cleanup’(调用sys.sp_MScdc_cleanup_job来清理过期的变更历史记录)

    如果上述中间的第三个步骤出现问题,也即后台进程无法解析日志后释放可用的日志空间,再次往数据库中写入操作,就会出现:数据库“TestDB”的事务日志已满,原因为“REPLICATION”的情况

    3>先创建复制发布,再使用CDC

    本文通过通过演示开启CDC的情况下日志空间被占满的现象,以及对应的处理办法

    创建复制时在分发服务器上创建日志读取代理作业,使用CDC时只在当前实例的代理上创建作业‘cdc.DemoDB3_cleanup’

     

    4>先使用CDC,再创建复制

    测试环境搭建

    使用CDC时,会在当前实例的代理上创建两个作业‘cdc.DBName_capture’和‘cdc.DemoDB3_cleanup’,然后在创建复制发布时,删除作业‘cdc.DBName_capture’,然后在分发服务器上创建日志读取代理作业。

      首先建立一个测试数据库,

    当数据库上最后一个复制发布删除时,如果数据库还在使用CDC,则会删除复制的日志读取代理作业,创建一个CDC作业‘cdc.DBName_capture’。

    USE master
    GO
    CREATE DATABASE TestLogFull ON PRIMARY 
    ( 
        NAME = N'TestLogFull', 
        FILENAME = N'D:DBFileTestLogFullTestLogFull.mdf' , 
        SIZE = 500MB , 
        MAXSIZE = UNLIMITED, 
        FILEGROWTH = 100MB 
    )
    LOG ON 
    (
        NAME = N'TestLogFull_log', 
        FILENAME = N'D:DBFileTestLogFullTestLogFull_Log.ldf' , 
        SIZE = 1MB , 
        MAXSIZE = 512MB 
    )
    

    当数据库上最后一个表上CDC被禁用时,不会删除CDC的作业,而如果在数据库级别禁用CDC时,会删除CDC相关的两个作业。

      这里指定日志文件的最大为512M,主要是为了演示日志空间被占满的现象

     

      接着开启新建一个表同时开启CDC来测试

    MSDN如是说:

    USE TestLogFull
    --启用CDC
    EXECUTE sys.sp_cdc_enable_db;
    GO
    
    --创建一张测试表
    create table test_cdc
    (
        id int identity(1,1) primary key,
        name nvarchar(50),
        mail varchar(50),
        address nvarchar(50),
        lastupdatetime datetime
    )
    
    --对表启用CDC
    EXEC sys.sp_cdc_enable_table 
        @source_schema            = 'dbo',
        @source_name              = 'test_cdc',
        @role_name                = 'cdc_admin',
        @capture_instance         = DEFAULT,
        @supports_net_changes     = 1,
        @index_name               = NULL,
        @filegroup_name           = DEFAULT
    

    当日志读取器代理同时用于变更数据捕获和事务复制时,复制的更改将首先写入分发数据库。  然后,捕获的更改会写入更改表。 两项操作会一起提交。 如果在写入分发数据库时有任何滞后时间,则在更改显示在更改表中之前,将有对应的滞后时间。

      CDC开启成功,开始测试日志被占满的情况

     

    新葡亰496net 30

    总结:

      这里演示对某些表开启CDC的情况下日志文件文件被占满的情况

    1.当复制和CDC一起使用时,CDC会使用复制的日志读取代理作业,代理作业读取到日志后,会优先将数据写入到分发库,然后再将数据写入到CDC的历史变更表中。

     

    2. 无论在多少张表上启用CDC或创建多少个发布,一个数据库上只能有一个作业负责读取日志。

    1,代理服务器未启动导致日志空间被占满

    1. 默认情况下,日志需要等待被复制和CDC处理完成后才会被同步到镜像端。

    文中一开始提到的步骤3,对于CDC,进程就是SQL Server Agent中的cdc.***_capture作业或者复制代理作业来读取日志
    如果SQL Server Agent在开启了CDC或者复制之后被关闭,或者重启服务器之后SQL Server Agent没有随机自动启动
    就有可能造成步骤2中的日志积压,也就是记录数据变化之后的事务日志处于replication状态,无法重用,导致没有可以使用的日志
    致使发生操作数据库的时候提示The transaction log for database '***' is full due to 'REPLICATION'.

     

      这里暂时关闭代理服务(仅仅是为了测试演示这一现象)

    JD DBR(肖磊削一刀)补充:

      新葡亰496net 31

    CDC和复制共同使用会有一些莫名其妙的bug,而这些bug不能完全重现,尚不知道因何引起,因此不推荐两者一起使用。

      增删改都可以产生事务日志,这里就演示insert数据的情况,做一个写数据的SQL,往开启了CDC的表中写数据库
      在建库的时候日志文件有限制成了512M,因为这个表上开启了CDC,写数据这个过程会产生事务日志,日志有空空间限制
      在写入数据的过程中,一开始是没有问题的,随着数据的不断写入(Replication状态的日志不断积压),当日志全部使用之后,下面的报错就会产生了

     ===============================================================================================

      新葡亰496net 32

    肖磊提到:在复制和CDC均有的环境中,直接删除最后一个发布将导致logreader被删除,即便CDC重新创建capture,但也会报错,貌似是LSN滞后的错误,导致CDC失效;

     

    测试1:

      此时观察事务日志的使用情况,发现已经是完全使用了,

    步骤:搭建事务复制和CDC,事务复制使用表TB2,CDC使用表TB1,在对表TB1循环插入数据的同时,删除复制发布。

    新葡亰496net 33

    结果:复制发布被成功移除,新的capture作业被新建,历史跟踪表中数据未丢失(操作期间所有的操作都被写入到历史表中)

      因为日志空间被完全使用了,那么观察一下日志的等待状态,是Replication状态

    PS: 肖大侠所遇问题的场景与测试1的场景类似。

      新葡亰496net 34

     

      此时尝试收缩也是无效的,因为日志都是出于活动状态,活动状态的日志是无法收缩的

    测试2:

    新葡亰496net,  新葡亰496net 35

    步骤:在表TB1上启用CDC,然后在表TB1上创建快照复制,然后删除快照复制(UI操作)

      可见,因为代理被关闭,读取日志的作业无法执行,造成日志堵塞,那么开启代理来看看到底行不行?
      开启代理,查看CDC作业的执行情况,会发现,此时代理作业也不好使了,作业执行的时候并没有成功,一样提示说事务日志已满

    结果:删除失败

      新葡亰496net 36

    解决办法:在表和数据库上禁用CDC后,可以正常删除快照复制

      此时观察测试表的cdc目标表没有任何数据,说明此时即便开启了代理,cdc的作业依然没有成功执行
      那么这里为什么CDC的代理作业也无法正常执行?
      其实也不难理解,cdc的作业也是读取事务日志写数据的,这中间也相当于有事务性操作,必须要借助日志来实现,而此时又没有可用的日志空间,
      这个作业当然要失败了。

     

    新葡亰496net 37

    测试3:

      那么此时怎么办?
        既然是日志堵塞了,就想办法清理到这部分活动日志,尝试将事务日志标记为已分发(虽然这里是CDC,但是对于日志的使用应该是跟复制一样的)

    步骤:在表TB1上启用CDC,然后在表TB1上创建事务发布,并创建订阅,保证订阅成功运行,在对表TB1循环插入数据的同时,删除复制发布。

      新葡亰496net 38

    结果:复制发布被成功移除,新的capture作业被新建,历史跟踪表中数据未丢失(操作期间所有的操作都被写入到历史表中)

      根据本人的测试,在执行上面的语句,将复制的事物标记为已分发之后,
      再次查看日志使用率,发现还是100%,但是尝试写入数据的时候是成功的,再次写入数据(一条即可)之后,日志空间开始释放,
      应该是写入时候的时候触发被标记为已分发的日志截断,也就是将上面占用了100%的日志空间释放出来
      然后再观察日志的使用率,发现如预期的,这部分日志已被截断,日志空间不再是被完全占用了,日志变成Nothing状态(可重用)

     

      新葡亰496net 39

    测试总结:

      这个测试说明,如果开启了CDC,SQL Server代理没有正常启动或者对应的作业没有正常启动,日志空间会随着不断产生的事物被占满,导致数据库无法进行写入性操作  

    在测试中未能重下肖大侠所说的问题,由于测试的局限性,肖大侠所说的问题仍需要考虑

        这里是用过手动标记日志为已分发的方式来释放日志的,这种情况下会导致cdc日志断裂的情况,也就是手动释放的日志无法传递到下游(cdc日志表)
      毕竟不是一个太好的办法,下面会说明另外一种办法。

     

     

    解决办法猜想:

    2,短时间内较大的事务性操作导致的日志空间被占满的情况

    如果按肖大侠所说的LSN问题,那么是否可以在删除复制之前停用复制,然后再删除发布,这样是否可能降低问题出现的概率呢?

        对去上面所说的代理服务被关闭导致日志堵塞的情况不同,这里直接开启代理服务,依旧拿着下面的脚本往表中写数据(比如实际业务中批量导入数据之类的)
        在写入一段时间之后,依然出现了事务日志被填满的情况,这又是为什么?

     

    新葡亰496net 40

    =================================================================================================

        还要从CDC的代理任务说起,这个代理的JOB虽然是连续执行的,但是因为上面写数据的时候也是连续写入的,也就是日志是连续产生的,
        因为限制了日志文件的大小(这里为了方便演示,限制为512M),日志文件有最大使用空间的限制。
        这里可以认为是一个Session消耗日志空间(Insert操作),一个进程解析日志之后释放日志空间(代理作业),
      但是消耗的速度要高于释放的速度,一旦日志空间被使用完,CDC的代理作业也无法完成,
        这样就又造成了上面的情况:日志空间被填满,数据库无法执行任何写入操作,CDC作业也无法执行从而释放可重用的日志空间,
        上面是通过手动标记事务日志的状态来解决日志文件被填满的,
        直接手动标记日志为已分发的做法是有点不合适的,
        一旦标记日志状态为已分发,接下来他就不会传递给CDC的系统表或者订阅端了
      这里通过另外一种方法来解决此问题:既然当前日志占满了,就在添加一个日志,注意新加日志初始化的空间不要太小。
      (有兴趣测试的盆友,这里添加完日志文件后注意耐心等待一两分钟)然后随后的CDC作业会借助新加的这个日志空间会继续执行

    一台服务器上出现复制问题,日志读取出现问题,重启日志读起代理依然报错,错误提示如下:

      新葡亰496net 41

    错误消息:
    进程无法在“WIN-SL4UN7FJ2UJSQL_MASTER”上执行“sp_replcmds”。 (源: MSSQL_REPL,错误号: MSSQL_REPL20011)
    获取帮助: http://help/MSSQL_REPL20011
    未能在变更数据捕获变更表中插入行。请参阅当前会话中的以前错误以确定原因,并更正所有关联的问题。 (源: MSSQLServer,错误号: 22863)
    获取帮助: http://help/22863
    进程无法在“WIN-SL4UN7FJ2UJSQL_MASTER”上执行“sp_replcmds”。 (源: MSSQL_REPL,错误号: MSSQL_REPL22037)
    获取帮助: http://help/MSSQL_REPL22037
    

      如果是当前逻辑此磁盘空间充足,也可以通过扩大事务日志文件来实现

    经调查,发布中的部分表开启了CDC功能。
    解决办法:

    ALTER DATABASE TestLogFull
    MODIFY FILE (
                    NAME = N'TestLogFull_log', 
                    FILENAME = N'D:DBFileTestLogFullTestLogFull_log.ldf' , 
                    SIZE = 600MB , 
                    MAXSIZE = UNLIMITED, 
                    FILEGROWTH = 100MB 
                )
    

    1.禁用表和数据库上的CDC

      此种情况说明,如果限制了日志的大小(或者存储日志的磁盘空间不足),数据库中开启了CDC或者复制,
      一旦数据出现大批量持续性写入操作(增删改),此时会出现SQL Server代理解析并释放日志的速度跟不上,也有可能造成日志被占满的情况

    2.重新初始化订阅

      

    3.开启数据库和表上的CDC

    3,不增加日志文件空间或者添加日志文件情况下重启SQLServer服务

    =================================================================================================

      这个办法也是本人在重现这一现象并尝试解决的时候试出来的,可行性不是太强,但还是说明一下,那就是重启大法,同时重启之后日志文件也发生了一些有意思的变化
      建库的时候日志文件限制为最大512M,同时没有手动标记标记日志为已分发状态,但是重启SQLServer服务之后,如果存放日志的磁盘有空间,这个日志会自动扩充一部分
      然后有了这部分扩充出来的日志,代理job就可以解析Replication状态的日志(之后)就可以释放日志空间了(需要一段时间来解析并释放日志,根据待复制的日志量有关)
      下图可以明显看到,日志限制为512MB,但是初始化为556MB,明显大过最大日志大小,这个是归功于重启SQLServer服务的结果

     参考链接:

      一下是在SQL Server 2014 SP2版本下测试的现象,

    1>禁用表上CDC )

      新葡亰496net 42

    2>禁用数据上CDC

       如果是SQL Server 2014(非SP2补丁版),开启CDC的方式占满日志则不会出现如下的情况,也就是说重启有日志并不会自动扩充一部分,
       我也是醉了,验证个东西真不容易,这些小细节跟补丁版本也有关系,不过这种偏门的方法不能作为经验!

     

     

    惯例上图招狼

     

    新葡亰496net 43

    总结:

      当开启了CDC之后,在相关表上的变化会写入事务日志(日志状态为Replication状态),
      代理任务会解析日志,解析完日之后标记日志为可重建状态(如果是简单还原模式,是可重用,如果是完整还原模式,日志备份也无法截断Replication状态的日志),
      这种状态下如果限制了日志的最大大小比较小,或者没有限制,存储日志的磁盘空间不足,
      在大批量写入数据(增删改)的时候,有可能产生的日志占满日志文件的情况,
      会导致释放日志的代理作业无法进行,代理作业无法进行又无法释放日志,仿佛是死循环。
      此时要么新增日志文件或者增加日志文件的最大大小,要么通过执行系统存储过程sp_repldone来标记事务为已分发(标记事务日志可重用)来解决这一问题。

    本文由新葡亰496net发布于网络数据库,转载请注明出处:新葡亰496net:的由来深入分析和消除办法,监察

    关键词:

上一篇:MySQL主键设计,mysql基本操作

下一篇:没有了