从生产中刷新测试数据库中的几个表的最佳方法是什么?


12

我在SQL Server 2008R2中有一个非常大的生产数据库和一个非常大的测试环境数据库。这两个数据库的表结构相似,但用户/登录/权限/角色不同。

我只需要每月从生产中定期刷新测试数据库中的几个表即可。

我正在计划执行此操作的当前方法是

  1. 使用BCP实用程序从生产中导出我需要的表。
  2. 将bcp导出文件复制到测试服务器上
  3. 在测试中刷新的所有表上禁用索引和约束
  4. 截断测试数据库表
  5. 使用BCP将数据加载回Test数据库表中。
  6. 在测试中重建索引并重新启用约束

对于这么小的任务,这一切似乎都太复杂了。似乎还会产生很多重做(在t-log中),是否有更好的方法呢?

我想到的另一种方法是将生产环境中的备份还原到测试环境中-但是我的问题是完整备份会很大,而且我不需要刷新所有表,只需要刷新几个表即可。 -并且生产数据库中的用户和安全性与测试不同。如果还原整个数据库,那么生产数据库中的安全设置将覆盖该设置。


Answers:


4

有两种方法可以满足您的需求:

(注意:如果表是由外键引用的,则将无法使用TRUNCATE。必须将其删除。或者,可以删除所有索引+外键并加载数据,然后重新创建它们)。

  • BCP OUT和BULK INSERT INTO目标数据库

    • 确保将测试数据库置于简单/批量记录恢复模式。
    • 启用跟踪标志610-将最少记录的插入到索引表中。

      /************************************************************************************************************************************************
      Author      :   KIN SHAH    *********************************************************************************************************************
      Purpose     :   Move data from one server to another*********************************************************************************************
      DATE        :   05-28-2013  *********************************************************************************************************************
      Version     :   1.0.0   *************************************************************************************************************************
      RDBMS       :   MS SQL Server 2008R2 and 2012   *************************************************************************************************
      *************************************************************************************************************************************************/
      
      -- save below output in a bat file by executing below in SSMS in TEXT mode
      -- clean up: create a bat file with this command --> del D:\BCP_OUT\*.dat 
      
      select '"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\bcp.exe" '-- path to BCP.exe
              +  QUOTENAME(DB_NAME())+ '.'                                    -- Current Database
              +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.'            
              +  QUOTENAME(name)  
              +  ' out D:\BCP_OUT\'                                           -- Path where BCP out files will be stored
              +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
              +  REPLACE(name,' ','') 
              + '.dat -T -E -SSERVERNAME\INSTANCE -n'                         -- ServerName, -E will take care of Identity, -n is for Native Format
      from sys.tables
      where is_ms_shipped = 0 and name <> 'sysdiagrams'                       -- sysdiagrams is classified my MS as UserTable and we dont want it
      and schema_name(schema_id) <> 'some_schema_exclude'                     -- Optional to exclude any schema 
      order by schema_name(schema_id)                         
      
      
      
      --- Execute this on the destination server.database from SSMS.
      --- Make sure the change the @Destdbname and the bcp out path as per your environment.
      
      declare @Destdbname sysname
      set @Destdbname = 'destination_database_Name'               -- Destination Database Name where you want to Bulk Insert in
      select 'BULK INSERT '                                       -- Remember Tables **must** be present on destination Database
              +  QUOTENAME(@Destdbname)+ '.'
              +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.' 
              +  QUOTENAME(name) 
              + ' from ''D:\BCP_OUT\'                             -- Change here for bcp out path
              +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_'
              +  REPLACE(name,' ','') 
              +'.dat'' 
              with (
              KEEPIDENTITY,
              DATAFILETYPE = ''native'',  
              TABLOCK
              )'  + char(10) 
              + 'print ''Bulk insert for '+REPLACE(SCHEMA_NAME(schema_id),' ','') + '_'+  REPLACE(name,' ','')+' is done... '''+ char(10)+'go' 
      from sys.tables
      where is_ms_shipped = 0 and name <> 'sysdiagrams'           -- sysdiagrams is classified my MS as UserTable and we dont want it
      and schema_name(schema_id) <> 'some_schema_exclude'         -- Optional to exclude any schema 
      order by schema_name(schema_id)

-

  • 方法2:SSIS-在这种情况下,我的首选方法。

    • 无需暂存到磁盘。所有处理都在内存中完成。
    • 您可以每月使用sql代理作业计划SSIS包,以自动将表从PROD刷新到TEST服务器。
    • 选择“ 快速加载 ”选项
    • 确保您为每个批号选择一个好的行(如果选择的行太高,则会出现锁升级-保持低于5K)

参考:《数据加载性能指南》以及我的回答-插入表中select * from table vs批量插入


1
SSIS绝对是走这里的路。数据抽取是设计要执行的任务。
Steve Mangiameli,2015年

3

无需进行备份和还原,也不需要调用/协调外部进程(例如BCP),甚至不需要与SSIS搞混(功能非常强大,非常酷,但是如果可以避免的话,我当然会:)。您可以在T-SQL的舒适环境中,可以通过SQL Agent进行调度的存储过程或每月运行一次的脚本中处理所有这些问题(尽管将它放在proc中并且长期进行调度的工作量较小)跑)。怎么样?通过使用SQLCLR来访问SqlBulkCopy.NET中的类,因为它实质上是BCP,而没有调用BCP的所有麻烦。您可以自己编写代码:没有任何超级复杂的设置或SqlBulkCopy该类几乎可以为您处理所有事情(您可以设置批处理大小,是否触发触发器等)。或者,如果您不想弄乱编译和部署程序集,则可以使用预构建的SQLCLR存储过程,例如DB_BulkCopy,它是SQL# SQLCLR库的一部分(我是该库的作者,但已存储了该存储过程)程序为免费版本)。我将在以下答案中对此进行更详细的描述,包括一个使用DB_BulkCopy的示例:

将数据从一个数据库导入到另一个脚本

如果不清楚将其放置在当前计划中的何处,则可以执行以下操作:

  • 删除步骤1和2(呜呼!)
  • 将步骤5替换EXECDB_BulkCopy或您自己编写的任何名称,它将数据从点A移到点B。

另外,应该指出SqlBulkCopyDB_BulkCopy

  • 可以接受任何结果集:是存储过程的SELECT还是EXEC都无关紧要
  • 对这些表中的任何一个进行模式更改时,更新非常容易;只是更改存储过程中调用此SQLCLR存储过程的查询
  • 允许重新映射字段(如果需要)

有关通过SqlBulkCopy进行的最小记录操作的更新

可以获取最少记录的操作,但是您应该知道:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.