金沙棋牌app手机下载

当前位置:金沙棋牌 > 金沙棋牌app手机下载 > Server主从一致性,SP2新增的数据库克隆功能

Server主从一致性,SP2新增的数据库克隆功能

来源:http://www.logblo.com 作者:金沙棋牌 时间:2019-11-29 12:44

SQL Server2014 SP2新增的数据库克隆功能

 

创建测试库

--创建测试数据库
create database testtest


use testtest
go
--创建表
create table testtest(id int ,name varchar(20))
--插入数据
insert into testtest select 1,'sdfsdf'



--创建存储过程
create proc testproc 
as 
select 1

 

 

 

创建克隆数据库的命令形式

DBCC CLONEDATABASE  (source_database_name, target_database_name)       –– Default CLONE WITH SCHEMA, STATISTICS and QUERYSTORE metadata.

DBCC CLONEDATABASE  (source_database_name, target_database_name) WITH NO_STATISTICS        –– SCHEMA AND QUERY STORE ONLY CLONE

DBCC CLONEDATABASE  (source_database_name, target_database_name) WITH NO_QUERYSTORE       –– SCHEMA AND STATISTICS ONLY CLONE

DBCC CLONEDATABASE  (source_database_name, target_database_name) WITH NO_STATISTICS,NO_QUERYSTORE    –– SCHEMA ONLY CLONE

 

 

 

开始创建克隆库

DBCC CLONEDATABASE  (testtest, testtestclone)         
已开始对“testtest”执行数据库克隆操作,目标为“testtestclone”。
已完成对“testtest”执行数据库克隆操作。克隆数据库为“testtestclone”。
数据库“testtestclone”是克隆数据库。克隆数据库应仅用于诊断目的,不得用于生产环境。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

 

 

 

创建成功之后,克隆库是只读状态的,并且库里所有表都没有数据

金沙棋牌app手机下载 1

金沙棋牌app手机下载 2

 

存储过程也会克隆过来,在克隆库打开存储过程定义

金沙棋牌app手机下载 3

 

金沙棋牌app手机下载,克隆库也会在数据目录下创建mdf和ldf文件

金沙棋牌app手机下载 4

金沙棋牌app手机下载 5

 

 

可以看到,克隆库其实跟源库没有太大差别,只是克隆库里面没有业务数据

 

利用克隆库诊断数据库问题,把克隆库进行数据库备份或分离数据库然后发给SQL Server专家就可以帮你诊断了,非常方便

--备份克隆库
backup database [testtestclone] to disk='D:DBBackuptesttestclone.bak' with compression,stats=5


--还原克隆库
USE [master]
RESTORE DATABASE [testtestclone] 
FROM  DISK = N'D:DBBackuptesttestclone.bak' WITH  FILE = 1, 
MOVE N'testtest' TO N'D:DataBasetesttest_843330487.mdf',  
MOVE N'testtest_log' TO N'D:DataBasetesttest_log_82742540.ldf', 
NOUNLOAD,  STATS = 5

GO

--分离克隆库
USE [master]
GO
EXEC master.dbo.sp_detach_db @dbname = N'testtestclone'
GO

 

金沙棋牌app手机下载 6

只要对方还原你的数据库就可以对你的数据库问题进行诊断了

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o 

本文版权归作者所有,未经作者同意不得转载。

Windows和Linux都有的Copy-on-write技术

 

MySQL技术内幕Innodb存储引擎第2版 P375

SQL Server2008 实现与维护(MCTS教程)P199

 

LVM快照技术

金沙棋牌app手机下载 7

LVM使用写时复制copy-on-write技术来创建快照,当创建一个快照时,仅复制原始卷中数据的元数据metadata,并不会有数据物理操作,因此快照创建过程非常快。当快照创建完成,原始卷上有写操作时,快照会跟踪原始卷块的改变,将要改变的数据在改变之前复制到快照预留空间里,因此这个原理的实现叫写时复制。对于快照读取操作,如果读取的数据块是创建快照后没有修改过的,那么会重定向读取操作到原始卷,如果读取的是已经修改过的块,读取保存在快照中该块在原始卷改变之前的数据,简单来将就是读取快照中的数据,因此采用写时复制机制保证了读取快照得到的数据和快照和快照创建时一致

简单来讲:

写:有变更写快照,无变更不写快照,写快照是变更之前的版本

 

SQL Server的快照技术

金沙棋牌app手机下载 8

SQL Server使用写时复制copy-on-write,SQL Server对区extent进行读写,首次对一个区中的数据页进行修改时,SQL Server将区的前影像复制到数据快照。

读取select:无更改过的,读取源库,更改过的,读取快照

由于在首次发生改变时写入了区的前影像,所以SQL Server一方面允许对源库进行更改
另一方面保证对数据库快照的任何查询不会反映创建快照之后发生的任何改变

最初的更改写入区的一个页,而且SQL Server将这个区的前影像写入数据库快照之后,写时复制功能会忽略后续对这个区的任何更改

由于可以为一个源库创建多个数据库快照,所以凡是没有获得区的副本的数据库快照都会被写入区的一个前影像

 

原理跟Linux LVM的快照原理是一样的!

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o 

用脚本定时监控SQL Server主从一致性

首先说一下我们的环境

我们使用的是事务复制,复制是单向的,主服务器和从服务器都在同一个机房,当然不同机房也可以,只需要改一下IP和端口

下面的脚本在我们的SQLServer 2008上已经应用,暂时没有发现问题,当然,如果大家使用过程中有发现问题欢迎向我反馈o(∩_∩)o 

 

首先,我们为什麽要校验呢?

我们知道因为网络延迟,或者从库有写入的情况(当然一般我们在订阅端会设置为db_datareader,不允许写)会造成主从数据不一致的情况

无论是SQL Server还是MySQL,所以我们就需要进行数据校验,以便大概知道我们的数据什么时候开始不一致

而校验是不可能每时每刻都做校验的,因为需要读取全表数据,对性能会有影响

 

 

下面的过程只需要远程上去从服务器,也就是订阅服务器上面做就可以了,完全不需要远程主服务器也就是发布服务器

线上我们做复制的表都比较小,数据量也不大

我们做复制的最大一个表是600MB的表 

600MB的表 校验时间是1 分钟,那么可以推算 50000MB(50GB)的表 大概80分钟 ,至于这个时间根据不同的环境 硬件和软件 所需的校验时间可能会有所不同

我们使用的服务器是DELL R720 

 

这个脚本原理很简单,就是利用SQL Server的job每天定时执行来获取主从上面的数据,从而判断主从数据是否一致

废话不说了,上脚本


1、在订阅端执行查看哪些表做了复制

首先你需要知道你现在哪些表是做了复制的,当然有些人会到发布服务器上去看,点击几下按钮,其实在订阅端是有视图可以看出

当前哪些表做了复制的

--在订阅端执行
use [Task] -- 要复制的库
GO



select article from dbo.MSreplication_objects
group by article
GO

有9个表做了复制

金沙棋牌app手机下载 9

 

2、建立linkedserver

金沙棋牌app手机下载 10金沙棋牌app手机下载 11

--建立linkedserver
USE [master]
GO

DECLARE @IP NVARCHAR(MAX)
DECLARE @Login NVARCHAR(MAX)
DECLARE @PWD NVARCHAR(MAX)

SET @Login = N'xxx' --★Do
SET @PWD = N'xxx'  --★Do
SET  @IP ='192.168.100.6,1433'


EXEC master.dbo.sp_addlinkedserver @server = @IP,@srvproduct = N'SQL Server'

EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'collation compatible', @optvalue = N'false'
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'data access', @optvalue = N'true'
EXEC master.dbo.sp_serveroption @server = @IP, @optname = N'dist',@optvalue = N'false'
EXEC master.dbo.sp_serveroption @server = @IP, @optname = N'pub',@optvalue = N'false'
EXEC master.dbo.sp_serveroption @server = @IP, @optname = N'rpc',@optvalue = N'true'
EXEC master.dbo.sp_serveroption @server = @IP, @optname = N'rpc out',@optvalue = N'true'
EXEC master.dbo.sp_serveroption @server = @IP, @optname = N'sub',@optvalue = N'false'
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'connect timeout', @optvalue = N'0'
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'collation name', @optvalue = NULL
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'lazy schema validation', @optvalue = N'false'
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'query timeout', @optvalue = N'0'
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'use remote collation', @optvalue = N'true'
EXEC master.dbo.sp_serveroption @server = @IP,@optname = N'remote proc transaction promotion',@optvalue = N'true'

USE [master]
EXEC master.dbo.sp_addlinkedsrvlogin 
@rmtsrvname = @IP,
@locallogin = NULL, 
@useself = N'False', 
@rmtuser = @Login,
@rmtpassword = @PWD

View Code

建立linkedserver的目的是连接到发布服务器获取数据,如果是不同机房,那么只需要改IP为公网IP和端口就可以了

 

3、在订阅服务器上建表

在订阅端建立两个表,这两个表的作用是保存校验数据

我说一下Repl_NeedMonitor表的need_monitor 字段,如果你有一天不想监控某个表了,你需要将那个表的need_monitor 字段改为0就可以了

Repl_NeedMonitor表需要预先插入你要监控的表,在这里第一步的“在订阅端执行查看哪些表做了复制”为了这一步做铺垫的

执行完第一步,你知道有哪些表需要做监控,然后插入数据到Repl_NeedMonitor表就可以了

---建表
USE [Task]  --★Do  
GO

--要监控的表
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Repl_NeedMonitor]') AND type in (N'U'))
        BEGIN
            DROP TABLE [dbo].[Repl_NeedMonitor]
        END
CREATE TABLE [dbo].[Repl_NeedMonitor]
    (
      id INT IDENTITY(1, 1)
             PRIMARY KEY ,
      tbname NVARCHAR(400) UNIQUE ,
      need_monitor INT ,  --是否需要监控
      update_time DATETIME
    )


--监控情况表
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Repl_MonitorStatus]') AND type in (N'U'))
        BEGIN
            DROP TABLE [dbo].[Repl_MonitorStatus]
        END
CREATE TABLE [dbo].[Repl_MonitorStatus]
    (
      id INT IDENTITY(1, 1)
             PRIMARY KEY ,
      tbname NVARCHAR(500) ,
      is_Consistency INT ,  -- 一致为1,  不一致为0
      master_record BIGINT , --主库表记录数
      slave_record BIGINT ,  --从库表记录数
      update_time DATETIME  --更新时间
    )


--插入要监控的表数据
INSERT INTO [Repl_NeedMonitor]   --★Do  
        ( [tbname] ,
          [need_monitor] ,
          [update_time]
        )
VALUES  ( N'Site' , -- tbname - nvarchar(500)
          1 , -- need_monitor - int
          GETDATE()  -- update_time - datetime
        )

SELECT * FROM [Repl_NeedMonitor]

Repl_NeedMonitor

金沙棋牌app手机下载 12

 

4、创建执行数据一致性校验存储过程

金沙棋牌app手机下载 13金沙棋牌app手机下载 14

USE [Task]
GO
/****** Object:  StoredProcedure [dbo].[usp_ConsistencyCheck]    Script Date: 03/19/2015 15:36:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        <桦仔>
-- Create date: <2015.03.08>
-- Description:    <执行数据一致性校验>  
-- =============================================
CREATE PROCEDURE [dbo].[usp_ReplConsistencyCheck] ( @tbname NVARCHAR(500) )
AS
    BEGIN
        DECLARE @is_Consistency INT  --是否一致
        DECLARE @master_record INT  
        DECLARE @slave_record INT  
        DECLARE @SQL NVARCHAR(MAX)
        DECLARE @LinkServer NVARCHAR(100)  
        DECLARE @DBName NVARCHAR(100)
        DECLARE @SQLCountMaster NVARCHAR(MAX)
        DECLARE @SQLCountSlave NVARCHAR(MAX)


        SET @LinkServer = '192.168.100.6,1433'  --★Do  
        SET @DBName = 'Task'  --★Do  


--获取主库表的记录数
        SET @SQLCountMaster = '
SELECT TOP 1  sysindx.[rowcnt] FROM ' + '[' + @LinkServer + '].' + '['
            + @DBName + '].' + '[sys].[sysobjects] AS sysobj
INNER JOIN [' + @LinkServer + '].' + '[' + @DBName + '].'
            + '[sys].[sysindexes] AS sysindx ON sysobj.[id] = sysindx.[id]  AND  sysobj.[xtype] = ''u'' AND sysobj.[name] ='
            + '''' + @tbname + ''''



--获取从库表的记录数
        SET @SQLCountSlave = '
SELECT TOP 1  sysindx.[rowcnt] FROM ' + '[' + @DBName + '].'
            + '[sys].[sysobjects] AS sysobj
INNER JOIN [' + @DBName + '].'
            + '[sys].[sysindexes] AS sysindx ON sysobj.[id] = sysindx.[id] AND sysobj.[xtype] = ''u''  AND sysobj.[name] ='
            + '''' + @tbname + ''''


       --创建临时表保存临时结果
        IF EXISTS ( SELECT  * FROM    [tempdb]..sysobjects WHERE   id = OBJECT_ID('tempdb..#tmptb1') )
            BEGIN
                DROP TABLE [tempdb].[#tmptb1]
            END
        IF EXISTS ( SELECT  * FROM    [tempdb]..sysobjects  WHERE   id = OBJECT_ID('tempdb..#tmptb2') )
            BEGIN
                DROP TABLE [tempdb].[#tmptb2]
            END
        IF EXISTS ( SELECT  *  FROM    [tempdb]..sysobjects WHERE   id = OBJECT_ID('tempdb..#tmptb3') )
            BEGIN
                DROP TABLE [tempdb].[#tmptb3]
            END


        CREATE TABLE [#tmptb1] ( [is_Consistency] INT )-- 一致为1,  不一致为0 
        CREATE TABLE [#tmptb2]([master_record] BIGINT)--主库记录数
        CREATE TABLE [#tmptb3]([slave_record] BIGINT) --从库记录数


        INSERT  INTO [#tmptb2]( [master_record]) EXEC ( @SQLCountMaster)
        INSERT  INTO [#tmptb3]( [slave_record]) EXEC ( @SQLCountSlave)
        SELECT TOP ( 1 ) @master_record = [master_record]  FROM    [#tmptb2]
        SELECT TOP ( 1 ) @slave_record = [slave_record]  FROM    [#tmptb3]


        IF ( @master_record <> @slave_record )
            BEGIN 
                SET @is_Consistency = 0
            END
        ELSE
            BEGIN
                --显示订阅表里面有的记录不在发布表里面的记录有多少 如果不为0 即数据不一致
                SET @SQL = 'SELECT  COUNT(*) FROM  ( SELECT  *  FROM [dbo].[' + @tbname + ']' --发布表
                    + ' EXCEPT ' + 'SELECT * FROM  [' + @LinkServer + '].'
                    + '[' + @DBName + '].' + '[dbo].[' + @tbname + ']' --订阅表
                    + ') AS T;'

                INSERT  INTO [#tmptb1]([is_Consistency]) EXEC (@SQL)

                IF ( SELECT TOP 1 [is_Consistency] FROM   [#tmptb1]) <> 0
                    BEGIN
                        SET @is_Consistency = 0
                    END
                ELSE
                    BEGIN
                        SET @is_Consistency = 1
                    END
            END


        INSERT  INTO [Repl_MonitorStatus]
                ( [tbname] ,
                  [is_Consistency] ,
                  [master_record] ,
                  [slave_record] ,
                  [update_time]
                )
                SELECT  @tbname ,
                        @is_Consistency ,
                        @master_record ,
                        @slave_record ,
                        GETDATE()

    END

View Code

注意:脚本中凡是有--★Do 的都是你需要结合自己情况去修改的变量

这个脚本的原理很简单,是读取主库表的记录数,然后读取从库表的记录数,然后进行比较

当两边的记录数是一致的,那么再用EXCEPT  减法归零的方法比较两边表数据的内容是否一致

如果也是一致的,那么两边表的数据就是一致的,否则就是不一致的,这里有一个效率问题,就是首先判断记录数是否一致

如果不一致就没有必要再去比较内容一致了,最后把数据插入到表Repl_MonitorStatus

 

5、创建扫描要监控的表存储过程

这里用游标检查哪一个表需要进行校验,然后调用usp_ReplConsistencyCheck存储过程进行校验

金沙棋牌app手机下载 15金沙棋牌app手机下载 16

USE [Task] --★Do  
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        <桦仔>
-- Create date: <2015.03.08>
-- Description:    <扫描要监控的表>  
-- =============================================
CREATE  PROCEDURE [dbo].[usp_ReplScanMonitorTb]
AS
    BEGIN

        DECLARE @TBNAME NVARCHAR(100)

        DECLARE CurTBName CURSOR
        FOR
            --获取需要监控的表的表名
            SELECT  tbname
            FROM    [dbo].[Repl_NeedMonitor]
            WHERE   need_monitor = 1

        OPEN CurTBName
        FETCH NEXT FROM CurTBName INTO @TBNAME

        WHILE @@FETCH_STATUS = 0
            BEGIN  
                EXEC [dbo].[usp_ReplConsistencyCheck] @TBNAME
                FETCH NEXT FROM CurTBName INTO @TBNAME
            END
        CLOSE CurTBName
        DEALLOCATE CurTBName

    END

View Code

 

 

6、创建定时校验复制主从数据一致性JOB

每隔13个小时调用一次存储过程,当然这个调用频率可以结合实际情况进行修改

金沙棋牌app手机下载 17金沙棋牌app手机下载 18

USE [msdb]
GO
-- =============================================
-- Author:<桦仔>
-- Create date: <2015.03.8>
-- Description:    <定时校验复制主从数据一致性JOB>
-- ==============================================



--以什么登录用户身份运行作业
DECLARE @login_name NVARCHAR(100)
SET @login_name=N'sa'  --★Do


BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]]    Script Date: 03/16/2015 15:18:09 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'定时校验复制主从数据一致性JOB', 
        @enabled=1, 
        @notify_level_eventlog=0, 
        @notify_level_email=0, 
        @notify_level_netsend=0, 
        @notify_level_page=0, 
        @delete_level=0, 
        @description=N'定时校验复制主从数据一致性JOB', 
        @category_name=N'[Uncategorized (Local)]', 
        @owner_login_name=@login_name, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [ResetLoginPassword]    Script Date: 03/16/2015 15:18:10 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'ReplScanMonitorTb', 
        @step_id=1, 
        @cmdexec_success_code=0, 
        @on_success_action=1, 
        @on_success_step_id=0, 
        @on_fail_action=2, 
        @on_fail_step_id=0, 
        @retry_attempts=0, 
        @retry_interval=0, 
        @os_run_priority=0, @subsystem=N'TSQL', 
        @command=N'exec [dbo].[usp_ReplScanMonitorTb]', 
        @database_name=N'Task', 
        @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback


EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'执行频率', 
        @enabled=1, 
        @freq_type=4, 
        @freq_interval=1, 
        @freq_subday_type=8, 
        @freq_subday_interval=13, 
        @freq_relative_interval=0, 
        @freq_recurrence_factor=0, 
        @active_start_date=20110316, 
        @active_end_date=99991231, 
        @active_start_time=0, 
        @active_end_time=235959, 
        @schedule_uid=N'ddbd2dbc-ab05-4d0a-a4ca-60becc2620ac'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

GO

View Code

 

 看一下执行结果

SELECT * FROM [Repl_MonitorStatus]

金沙棋牌app手机下载 19

从作业历史里看一下总执行时间

金沙棋牌app手机下载 20

从执行结果里面也可以看到执行时间

金沙棋牌app手机下载 21

 

脚本缺陷

这个脚本是有缺陷的,如果你是复制表里面的几个字段而不是整表复制的话,那么他就不能比较两边的一致性了

情况一:只复制表里的几个字段,并只需要监控一张表

解决办法:在第一个存储过程里面《执行数据一致性校验》存储过程 修改一下下面的代码只select复制的字段,而不是select *

 --显示订阅表里面有的记录不在发布表里面的记录有多少 如果不为0 即数据不一致
                SET @SQL = 'SELECT  COUNT(*) FROM  ( SELECT  字段1,字段2。。。  FROM [dbo].[' + @tbname + ']' --发布表
                    + ' EXCEPT ' + 'SELECT  字段1,字段2。。。 FROM  [' + @LinkServer + '].'
                    + '[' + @DBName + '].' + '[dbo].[' + @tbname + ']' --订阅表
                    + ') AS T;'

 

情况二:只复制表里的几个字段,并且需要监控几张表,这些表中,有些表是整表复制,有些表只复制几个字段

由于脚本里面没有加入判断复制项目,那么对于这种情况,这个脚本无能为力

 


总结

在线上使用了事务复制这麽久不知道有多少人会定期的进行一下数据校验,当主库发生宕机的时候,你的从库的数据是否是一致的

如果你的主库因为硬件问题宕机,并且不能在最短的时间之内修复好,那么你这时再做主从数据的一致性校验已经没有可能了

这时候你有两个选择

1、冒险使用从库的数据,将从库变为主库

2、放弃使用从库,全部数据不要(当然了,全部数据不要是没有可能的!)

 

当然,这样直接在主库上进行select查询,会影响到主库的业务,严重的话,可能会遇到死锁

我们可以变通一下,使用快照数据库来解决,linkedserver连接到快照数据库进行数据内容对比

--进行数据对比之前先建立主库的数据库快照,再进行对比
CREATE DATABASE sss_ss ON
(NAME = N'sss', FILENAME = N'E:DataBasesss.ss' )
    AS SNAPSHOT OF [sss];
GO

--linkedserver直接连接到快照数据库进行对比
USE [sss_ss]
go

SELECT * FROM [dbo].[test]

------------------------------------------------
--对比完之后,再删除快照数据库
USE [master]
GO

DROP DATABASE [sss_ss]

 

 

至于在SQL Server中比较两张表的数据一致性的方法和性能,可以参考下面这篇文章

SQLSERVER中如何快速比较两张表的不一样 

 

 

如有任何问题,欢迎大家向我反馈o(∩_∩)o 

 

2015-3-23 补充:今天发现主从数据出现了不一致的情况

可以看到即使两边的数据记录是一样的,但是也不代表两边的数据是一致的,表里面的数据内容也有可能不一致

Dest这张表两边都是82条记录

金沙棋牌app手机下载 22

我们用SQL语句来检查一下

SELECT  *  FROM [dbo].[Dest]  EXCEPT 
SELECT * FROM  [192.168.100.116].[Task].[dbo].[Dest]



SELECT  *  FROM  [192.168.100.116].[Task].[dbo].[Dest]   EXCEPT 
SELECT * FROM  [dbo].[Dest]

发现了ID为36的这条记录的Pause字段不一样,第6台是,第11台是

金沙棋牌app手机下载 23

询问开发,开发说主那边是正确的,然后对那边进行update回去正确的数据

注意:从数据库是设置了db_datareader的,只有DBA才可以对从数据库进行update操作!

 

2015-3-24 补充:如果要复制的表中包含了smalldatetime数据类型,那么在except比较的时候会出现不一致的情况

金沙棋牌app手机下载 24

 

 

 

 

金沙棋牌app手机下载 25

表定义

CREATE TABLE [dbo].[Extension](
    [ID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [AddOn] [smalldatetime] NOT NULL,
    [Hash] [nchar](32) NULL)

linkserver查出来的smalldatetime数据类型带秒小数部分,而在本地查询不会出现这种情况

后来查了资料发现这中间有一个数据类型映射问题

解决方法有两个:

1、表定义的时候不用smalldatetime 而用datetime

2、脚本里对用了smalldatetime 类型的字段做一下数据类型转换

第二个解决方法要写更加多的动态SQL判断字段所用数据类型,拼接更加多的SQL

当然第一个解决方案会浪费空间,如果业务是不需要记录秒级的时间的,那么就浪费4个字节的空间了

 

详细可以查看MSDN

分布式查询的数据类型映射

 

本文由金沙棋牌发布于金沙棋牌app手机下载,转载请注明出处:Server主从一致性,SP2新增的数据库克隆功能

关键词: