sql server 快照
This article will review specific SQL Server merge replication issues related to foreign keys and schema snapshots
本文将回顾与外键和架构快照相关的特定SQL Server合并复制问题
问题 (Problem)
We have merge replication configured on a database to replicate data to different subscribers. While applying the initial snapshot to subscribers the merge agent fails due to foreign keys on non-replicating tables. In this article we’ll see how we solved this using pre and post snapshot scripts.
我们在数据库上配置了合并复制,以将数据复制到不同的订户。 在将初始快照应用于订户时,合并代理由于非复制表上的外键而失败。 在本文中,我们将看到我们如何使用快照前和快照后的脚本来解决这个问题。
解 (Solution)
There are few tables which are added to merge replication. These tables have primary key and are being referenced by foreign keys which were created on non-replicating tables. Now while applying the initial snapshot on subscribers, the merge agent tries to drop and re-create the table which throws error “The schema script could not be propagated to the subscriber. Could not drop object ‘dbo.tablename’ because it is referenced by a FOREIGN KEY constraint”.
合并复制时添加的表很少。 这些表具有主键,并由在非复制表上创建的外键引用。 现在,当在订阅服务器上应用初始快照时,合并代理尝试删除并重新创建表,这将引发错误“架构脚本无法传播到订阅服务器。 无法删除对象“ dbo.tablename”,因为它已被FOREIGN KEY约束引用。”
To illustrate this, I will create a table “PARENT” with primary key on both publisher and subscriber.
为了说明这一点,我将在发布者和订阅者上创建一个具有主键的表“ PARENT”。
CREATE TABLE PARENT (ID INT PRIMARY KEY, NAME VARCHAR (50))
Create a table with foreign key which refers to the “PARENT” table created above on both publisher and subscriber.
用外键创建一个表,该表引用上面在发布者和订阅者上创建的“ PARENT”表。
CREATE TABLE CHILD (ID INT, ADDRESS1 VARCHAR (50)
CONSTRAINT FK_CHILD FOREIGN KEY (ID) REFERENCES PARENT(ID))
Now I will create a merge publication and add the table “PARENT” to publication using SQL server management studio.
现在,我将创建一个合并发布,并使用SQL Server Management Studio将表“ PARENT”添加到发布中。
合并复制: (Merge replication:)
Login to SQL Server from SQL Server management studio. Assuming the distribution is already configured navigate to replication folder -> Local publications -> Right click on new publication. Please refer to the below image.
从SQL Server管理工作室登录到SQL Server。 假设已配置分发,请导航到复制文件夹->本地发布->右键单击新发布。 请参考下图。
Click on Next– > select the database where you created “PARENT” table. Click Next and select merge replication.
单击下一步 –>选择创建“ PARENT”表的数据库。 单击下一步,然后选择合并复制。
Click Next and check 2008 or later -> add table “PARENT” and click on article properties -> set properties of all table articles -> select drop existing object and create new one as shown below images.
单击下一步,然后检查2008或更高版本->添加表“ PARENT”,然后单击商品属性->设置所有表格商品的属性->选择删除现有对象并创建新对象,如下图所示。
Click Next– > Next-> Add filter in case if you want to send specific data to each subscriber or you can skip this step and click Next-> check create snapshot immediately to create snapshot on creation of publication and uncheck schedule the snapshot agent to run at following times.
如果要向每个订阅者发送特定数据,请单击“ 下一步” ->“ 下一步” ->“ 添加筛选器” ,或者可以跳过此步骤,然后单击“ 下一步” ->“立即检查创建快照”以在创建发布时立即创建快照,并取消选中将快照代理调度到在以下时间运行。
Click Next and add the credentials you want to use for snapshot agent and connecting publisher -> Next -> Next -> and input publication name and finish.
单击下一步,然后添加要用于快照代理和连接发布者的凭据-> 下一步 -> 下一步 ->并输入发布名称和完成。
Right click on the publication you just created and click on Launch replication monitor, click on the publication in replication monitor and click on the Agents tab as shown in below image and make sure the snapshot is completed.
右键单击刚刚创建的发布,然后单击“ 启动复制监视器” ,在复制监视器中单击发布,然后单击“代理”选项卡,如下图所示,并确保快照已完成。
Once the snapshot is completed we need to add the subscriber to publication we just created.
快照完成后,我们需要将订阅者添加到刚创建的发布中。
添加订户 (Adding a subscriber)
Navigate to publication you just created, right click on the publication and click on New subscription -> Next -> Next -> select the type of subscription you want (Pull or push) as per your need -> Next-> add the subscriber server and select the subscriber database. Add the logins to run merge agent, connect the publisher, distributor and the subscriber -> Next -> select agent schedule as per your need. In my case I selected run continuously -> Initialize immediately -> select subscription type as per your need -> check create subscriber and click Next -> Finish.
导航到您刚刚创建的发布,右键单击发布,然后单击“新建订阅”->“下一步”->“下一步”->根据需要选择想要的订阅类型(拉或推)->“下一步”->“添加订阅服务器”并选择订户数据库。 添加登录以运行合并代理,根据需要连接发布者,分发者和订阅者->下一步->选择代理时间表。 就我而言,我选择连续运行->立即初始化->根据您的需要选择订阅类型->检查创建订阅者,然后单击下一步->完成。
Now the merge agent runs and applies initial snapshot. While applying the initial snapshot the merge agent fails with error.
现在,合并代理将运行并应用初始快照。 应用初始快照时,合并代理失败,并显示错误。
“The schema script could not be propagated to the subscriber. Could not drop object ‘dbo.tablename’ because it is referenced by a FOREIGN KEY constraint” as shown in below image.
“架构脚本无法传播到订户。 无法删除对象“ dbo.tablename”,因为它已被FOREIGN KEY约束引用”,如下图所示。
This is due to foreign key on table “CHILD” which refer to primary key on “PARENT” table. This error would not appear if both tables are part of replication but the scenario here is only “PARENT” table is replicated.
这是由于表“ CHILD”上的外键引用了“ PARENT”表上的主键。 如果两个表都是复制的一部分,则不会出现此错误,但此处的情况是仅复制“ PARENT”表。
To fix this issue we need to drop the foreign key, apply the snapshot and then re-create the foreign key.
要解决此问题,我们需要删除外键,应用快照,然后重新创建外键。
We can manually run the script to drop foreign keys and recreate them after applying snapshot. But in case of many subscribers it would be bit difficult to run scripts manually. To automate this, we used pre and post snapshot scripts in merge replication.
我们可以手动运行脚本以删除外键并在应用快照后重新创建外键。 但是对于许多订阅者而言,手动运行脚本会有些困难。 为了实现这一点,我们在合并复制中使用了快照之前和之后的脚本。
之前和之后的快照脚本 (Pre and Post snapshot scripts)
These scripts are applied at subscriber before and after the snapshot. The location of these scripts is provided while configuring merge replication.
这些脚本在快照之前和之后在订阅服务器上应用。 这些脚本的位置是在配置合并复制时提供的。
These files are copied to snapshot folder by snapshot agent at the time of snapshot creation and applied at the subscriber. We need to take care of syntax errors or any other errors in these files else the merge agent fails while applying the snapshot and we must re-run the snapshot agent after fixing the errors in files.
这些文件在创建快照时由快照代理复制到快照文件夹,并在订阅服务器上应用。 我们需要注意这些文件中的语法错误或任何其他错误,否则合并代理在应用快照时会失败,并且必须在修复文件中的错误后重新运行快照代理。
These scripts should be created in a such a way that they can be re-run on subscriber during re-initialization process or in case of any failure while applying the snapshot.
这些脚本的创建方式应使其可以在重新初始化过程中或在应用快照时发生任何故障的情况下在订阅服务器上重新运行。
For example, if you are creating a foreign key or dropping a foreign key use if exist statements so that the script can be rerun in case of failures or re-initialization.
例如,如果要创建外键或删除外键,则使用if语句,以便在失败或重新初始化的情况下可以重新运行脚本。
In our case we added the drop foreign key statement in pre- snapshot script and create foreign key statement in post snapshot script. So that the foreign key is dropped before applying the snapshot and the snapshot is applied by merge agent and the foreign key is recreated after applying snapshot.
在本例中,我们在快照前脚本中添加了drop外键语句,并在快照后脚本中创建了外键语句。 这样,在应用快照之前就删除了外键,并由合并代理程序应用了快照,并在应用快照后重新创建了外键。
Please refer to below pre-snapshot script.
请参考以下预快照脚本。
if exists(select 1 from sys.foreign_keys where name = 'FK_CHILD')
BEGIN
ALTER TABLE [dbo].[CHILD] DROP CONSTRAINT [FK_CHILD]
END
This script checks for existence of foreign key and drop if exist in database. Please refer to the below post snapshot script.
if not exists (select 1 from sys.foreign_keys where name = 'FK_CHILD')
BEGIN
ALTER TABLE [dbo].[CHILD] WITH CHECK ADD CONSTRAINT [FK_CHILD] FOREIGN KEY([ID])
REFERENCES [dbo].[PARENT] ([ID])
NOT FOR REPLICATION
ALTER TABLE [dbo].[CHILD] CHECK CONSTRAINT [FK_CHILD]
END
These scripts are saved in a .sql file and the location is given in merge replication properties.
这些脚本保存在.sql文件中,并且位置在合并复制属性中给出。
Navigate to the publication -> right click on the publication -> Click on properties -> Click on snapshot -> Now input the location of pre and post snapshot files you created earlier. Please refer to the below image.
导航到发布->右键单击发布->单击属性->单击快照->现在输入之前创建的快照文件的位置。 请参考下图。
Once the location of pre and post snapshot scripts is updated in merge replication properties, generate the snapshot.
在合并复制属性中更新快照快照脚本之前和之后的位置之后,请生成快照。
Navigate to the publication -> Right click on the publication -> view snapshot agent status and click on Start.
导航到发布->右键单击发布->查看快照代理状态,然后单击开始。
We can also generate snapshot using replication monitor. Once the snapshot is generated we can see the pre and post snapshot file are copied from their locations to snapshot folder.
我们还可以使用复制监视器生成快照。 生成快照后,我们可以看到快照前和快照后的文件已从其位置复制到快照文件夹。
Now when the merge agent runs, the pre-snapshot script is applied first which drops the foreign key.
现在,当合并代理运行时,将首先应用pre-snapshot脚本,该脚本将删除外键。
Now the snapshot is applied which drops the “PARENT” table successfully as it has no foreign key references and the table is re-created. Now the foreign keys which are dropped as in pre snapshot script are created back using post snapshot script.
现在,将应用快照,该快照成功删除了“ PARENT”表,因为它没有外键引用,并且已重新创建该表。 现在,使用快照后脚本重新创建与快照前脚本中一样删除的外键。
We can create merge replication using scripts as well. I have replaced the database name with “yourdatabasename”.
我们也可以使用脚本创建合并复制。 我已将数据库名称替换为“ yourdatabasename”。
To enable replication on the database use below script. This script should be executed on master database.
要在数据库上启用复制,请使用以下脚本。 该脚本应在master数据库上执行。
exec sp_replicationdboption @dbname = N'yourdatabasename', @optname = N'merge publish', @value = N'true'
GO
Below are the procedures used in creating merge publication, adding snapshot agent, to grant access to publication and adding table to merge publication. These procedures should be run on publisher at publisher database with parameters as per your need.
以下是创建合并发布,添加快照代理,授予对发布的访问权限以及添加表以合并发布的过程。 这些过程应根据需要在发布者数据库的发布者上运行,并带有参数。
- sp_addmergepublication sp_addmergepublication
- sp_addpublication_snapshot sp_addpublication_snapshot
- sp_grant_publication_access sp_grant_publication_access
- sp_addmergearticle sp_addmergearticle
- sp_addmergesubscription sp_addmergesubscription
笔记: (Notes:)
The pre- and post-snapshot should be modified in case of any new foreign keys added during new releases.
如果在新版本中添加了任何新的外键,则快照前和快照后应进行修改。
These scripts should be prepared in such a way that they can be re-run.
这些脚本应以可以重新运行的方式进行准备。
These scripts should be run with sqlcmd to check for errors before.
这些脚本应与sqlcmd一起运行以检查错误。
Check permissions on these files to avoid permission issues while copying these files to the snapshot folder.
检查这些文件的权限,以避免在将这些文件复制到快照文件夹时出现权限问题。
It is always good to make changes to main scripts instead of the pre and post snapshot scripts that were copied to snapshot folder. So that we do not loose changes in further snapshots.
最好更改主脚本,而不要更改复制到快照文件夹的快照前脚本和快照后脚本。 这样我们就不会在进一步的快照中丢失更改。
目录 (Table of contents)
具有超过246列的表SQL Server复制 |
在SQL Server合并复制中应用快照时出现外键问题 |
SQL Server复制(合并)–复制什么,什么不复制 |
SQL Server复制(合并)–复制架构更改中的性能问题 |
合并SQL Server复制参数化的行筛选器问题 |
镜像数据库上的日志传送 |
sql server 快照