• SQL Server AlwaysON 同步模式的疑似陷阱


    SQL Server 2012 推出的最重要的功能之一Alwayson,是一个集之前Cluster和Mirror于一体的新功能,即解决了Cluster依赖共享存储的问题,又解决了镜像不能实时读以及转移后连接串需要添加转移IP的问题,看起来的确很实用。

    而且Alwayson多副本的功能为实现读写分离提供了可能,试想一下,当主副本压力比较大的时候,是否可以将读操作引向辅助副本呢?答案一般来讲是肯定的,请注意,是一般!

    Alwayson有两个同步模式,同步和异步,即然是同步,理所当然的我认为他是实时的,所以我配置了只读路由,来使用这个功能。

    遗憾的是,这个同步并不是数据的实时同步,当主副本数据发生变化时,同步模式下的辅助副本并不能立即取到变化的数据。

    实验如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    EXEC sp_addlinkedserver @server = N'Secondary', @srvproduct = N'',
        @provider = N'SQLNCLI', @datasrc = N'192.168.200.201';
     
    EXEC sp_addlinkedsrvlogin 'Secondary ', 'false ', NULL, 'sa', 'sqlcn.com'
     
    USE DemoDB
    go
     
    CREATE TABLE tb_alwayson
        (
          id INT IDENTITY
                 PRIMARY KEY ,
          name VARCHAR(200)
        )
     
    INSERT  INTO tb_alwayson
            ( name )
            SELECT  NEWID()
     
    SELECT  COUNT(*)
    FROM    tb_alwayson
    WAITFOR DELAY '00:00:00.900'
    SELECT  COUNT(*)
    FROM    Secondary.DemoDB.dbo.tb_alwayson

    使用连接服务器,这是一个非常好理解的测试办法,在我的环境里,你会发现,在辅助副本上要取到变化的数据,大概要900ms才能保证,900ms以下,都没法保证,甚至在300ms以下,没出现过一次能同步的情况。

    这就是同步模式,让你没有一点点儿防备

    image

    那么这个同步模式到底是怎么个同步呢?

    答案是这样的:它可以保证事务日志是同步的,也就是可以保证不丢失数据,但不能保证数据变化没有延时,这是由于辅助副本在接收主副本传来的Trans log时,首先将其缓到本地Log Cache,接着强制硬化到本地Ldf,然后随即向主副本告知你可以commit了,但注意,此时的硬化到本地ldf并非本地数据已经变化,这是因为辅助副本将trans log硬化到本地的同时,它是使用一个异步进程去redo这些trans log产生的Page变化到Data文件的,这也就决定了这个Redo的操作是不可能比硬化日志早的,所以数据的延时就是肯定的了。

    《SQL Server 2012实施与管理实战指南》中指AlwaysON同步过程如下:

    任何一个SQL Server里都有个叫Log Writer的线程,当任何一个SQL用户提交一个数据修改事务时,
    它会负责把记录本次修改的日志信息先记入一段内存中的日志缓冲区,然后再写入物理日志文件(日志固化)。
    所以对于任何一个数据库,日志文件里都会有所有数据变化的记录。
    对于配置为AlwaysOn主副本的数据库,SQL Server会为它建立一个叫Log Scanner的工作线程。
    这个线程专门负责将日志记录从日志缓冲区或者日志文件里中读出,打包成日志块,发送给各个辅助副本。
    由于它的不间断工作,才使主副本上的数据变化,可以不断地向辅助副本上传播。
    辅助副本上,同样会有两个线程,完成相应的数据更新动作,它们是固化(Harden)和重做(Redo)
    固化线程会将主副本Log Scanner所发过来的日志块写入辅助副本的磁盘上的日志文件里(这个过程被称为"固化")。
    而重做线程,则负责从磁盘上读取日志块,将日志记录翻译成数据修改操作,在辅助副本的数据库上完成。
    当重做线程完成其工作以后,辅助副本上的数据库就会跟主副本一致了。AlwaysOn就是通过这种机制,保持副本之间的同步。
    重做线程每隔固定的时间点,会跟主副本通信,告知它自己的工作进度。主副本就能够知道两边数据的差距有多远。

    这些线程在工作上各自独立,以达到更高的效率。Log Scanner负责传送日志块,而无须等待Log Writer完成日志固化;辅助副本完成日志固化以后就会发送消息到主副本,告知数据已经传递完毕,而无须等待重做完成。其设计目标,是尽可能地减少AlwaysOn所带来的额外操作对正常数据库操作的性能影响。

    image

    事实已经很清楚了,同步的原理决定了数据的延时,想用AlwaysON做读写分离的朋友们,考虑好你所能容忍的延时时间吧!

    另外,微软你敢在官方联机文档与各种技术大会上把同步模式非数据实时同步提一下吗?

  • 相关阅读:
    Go Map
    Go XORM
    Go切片
    Go函数
    dockerfile常用指令
    Goroutine并发控制
    Go 格式转换
    Go 常用知识点及实例
    Go 时间
    Go error
  • 原文地址:https://www.cnblogs.com/nzperfect/p/3752688.html
Copyright © 2020-2023  润新知