浏览模式: 普通 | 列表
分类: 数据同步和复制 | 1

[转]关于sql server数据同步msmerge表的说明 [私人]

[ 2008-11-16 11:00:31 | 作者: progame ]
MSmerge_contents causes problems for anyone that is running merge replication for any length of time. The problem is that MSmerge_contents will grow forever unless you manage it. Merge replication makes very heavy use of MSmerge_contents which can cause problems as the size grows. This is normally manifested by deadlocking and the entire replication system slowing down. This occurs, because the time to locate the appropriate rows increases as the size increases.
Before getting to the script itself, you have to understand what is going on and why we are purging the metadata.

The main tables for merge replication are MSmerge_contents, MSmerge_tombstone, and MSmerge_genhistory. In addition to these, there is a set of tables in distribution. For merge replication, distribution is NOT important. It simply contains status messages such as: agent started, agent stopped, agent retrying, etc. Don't bother to backup distribution and if you lose it, simply recreate it. MSmerge_tombstone contains a row for each row that was deleted from a published table. Each publication is configured with a retention period. The clean up jobs will remove anything older than this retention period. This applies to the messages in distribution and the rows in MSmerge_tombstone ONLY. It does not apply to anything else. When you issue a transaction against a published table, a trigger fires and makes entries in the merge metadata tables. Inserts and updates go into MSmerge_contents. All new rows get a generation of 0 (zero). MSmerge_genhistory is the keystone to the merge system and is what provides the power and flexibility. It contains a row for each row modified in each article in each publication. When the merge agent fires, it grabs all of the rows with a generation of zero. It then looks in the MSmerge_genhistory table and gets the highest generation value applied. It then sets the generation to the next highest value based on what was returned from MSmerge_genhistory ...

阅读全文...
To fix this problem, I did the following:

1. First found the duplicate generation(s):

select generation

from msmerge_genhistory

group by generation

having count(*) > 1

2. Then I scripted an update from the msmerge_contents table just to be safe (all of my tables have the column "last_modified". You will need to change this to an appropriate column):

select 'update ' + a.name + ' set last_modified = last_modified where rowguid = ' +''''+ cast(c.rowguid as nvarchar(40)) + ''''

from msmerge_contents c

join sysmergearticles a

on c.tablenick = a.nickname

where generation = 4784219

3. Then I deleted 1 of the rows from msmerge_genhistory for that generation.

4. Replication worked fine after that.

5. Run the update script created in step 2 on the publisher to reissue the updates.

Step 2 and 5 might be unnecessary. But i included it just in case.

在第二步时, msmerge_contents 找不到这个generation的数据, 于是只好直接做第三步

造型说明无效的字符值?

[ 2008-03-05 19:12:48 | 作者: progame ]
有一个订阅端一直不工作, 显示错误就是这个, 可怜啊, 所以说数据库最好还是装英文版, 出了错误好google, 就这个错误说明, 严重怀疑微软是全文翻译的使用者, 最后我猜我猜我猜猜猜, 想起以前可能有类似错误, 错误里应该有cast invalid这些字符, 于是和merge replication一搜, 终于明白了, 真正的错误描述应该是:
Invalid Character value for cast specification

看看这都差哪去了, 我们有理由相信这是临时工干的!

后来用-output 输出日志, 查出是哪个表的数据出现这种情况, 再清理了这个表的msmerge_contents信息, 基本搞定

select * from MSmerge_contents where tablenick in (
select nickname from sysmergearticles where name = '....')

客户的数据库又损坏了

操作系统损坏, 重装后数据库文件无法附加, 报803错误, I/O error. 对着两个二进制的文件当然没辙, 除非专业修复Sql Server的公司可以直接分析文件结构搞定它, 首先就是先复制这两个文件到别的地方备份先, 万一呆会的修复工作弄错了, 想要原来的数据都没办法了.

接下来先让Sql Server能够把它装载起来再说吧. 只好使用瞒天过海的杀手锏了, 建一个新的相同名称, 相同物理文件的数据库, 然后停掉SQL服务, 用损坏的数据库文件覆盖上去, 重启服务, SQL SERVER挣扎了半天, 终于还是认为这个数据库是错误的, 在管理器里显示不出此数据库, 于是只能再来:UPDATE sysdatabases SET status = status ^ 32768 WHERE name = ...

数据库可以出来了, 当然是紧急置疑模式, 用DBCC(之前可能要设置为单用户)检查, 发现有4处不一致错误, 索引上的就不用管了, 大不了重装索引, 关键是找到哪些表损坏了, 然后才能知道如何去凑这些数据, 通过循环一遍, 用select全部数据测试, 发现有一个单据表数据损坏, 无法全部select, 那么我现在要的就是它同步之后增加的数据, 用创建日期倒排序找后几条, 幸好这些数据不在坏的页面, 可以取出, 先不管, 用select into扔到pubs数据库里先存着. 其它未损坏的数据我要挪过去的话, 继续用刚才的循环执行数据来一遍select, 不过这次要into到新数据库去了, 尽管表的索引主键这些都不会在新数据库是创建, 但数据先过去再说, 然后sqldelta出山, 同步数据库结构, 这样sqldelta也不会发生使用临时表同步数据的方式, 保证了我的rowguid列里的值不被修改

到此为止, rowguid列的属性仍然没有修改过来, sqldelta无法处理这种情况, 损坏数据的表仍然未在新库中创建. 先修改rowguid属性吧, 照样来个大循环, 使用alter table alter column add rowguid就行了, 再从数据中心把这个分公司的单据表全部select into过来, 再从刚才的pubs临时表中它未同步的数据也select into where id not in ()过来, 然后用把这个表结构用刚才的方法搞定, 重建数据同步, 然后用我原来的修改数据但不影响数据的SQL以便让它再次收集所有行为数据更新, 再次向数据中心同步一次.

Sql Server数据同步之推拉式

[ 2007-03-13 22:49:46 | 作者: progame ]
推是Push,拉是Pull,两个长得倒是挺像的,别搞混了,为什么我们要分清推式订阅和拉式订阅呢?因为我们要解决在Internet动态IP的问题。

当我们的发布端是固定IP而订阅端为动态IP时,怎么办?那么只能是拉式订阅,因为订阅端主动到有固定IP的发布服务器去取数据,或者把自己的更新提交到发布服务器;当我们的发布端为动态IP时,那么只能是由发布端推给订阅端了,因为发布端知道订阅端的IP嘛,有目的地就可以直达了。

那么有人问了,如果两边都是动态IP怎么办?那么我们只好把它们变成静态了,怎么变?比如说通过VPN,那么相当于两个有固定IP的局域网内的Server,同步是完全没有问题的,而且还多了那么一点安全性,毕竟Sql Server不用暴露在外网上。

另外多说一句,Sql Server2005的集成界面真是不好用,完成一个任务得东点一下西点一下,要集成你就都集成吧,结果Replicaiton monitor还得单独启一个exe,不知怎么搞的。

进程未能将快照传送给订阅服务器

[ 2006-07-16 21:35:24 | 作者: progame ]
在一次SQL SERVER 2000重建同步中,居然报错:
进程未能将快照传送给订阅服务器
error detail 没有,于是使用 -output c:\log.txt 乱码!
难道因为装的是中文版的sql server? 怎么办?

只能傻干了,删除 重建,错误照旧

气愤中......

1234 转个圆圈 再来一次....

错误照旧,log又没有用,绝望+失望!!!

再来,这次终于老天被我的勤奋打动了,抛出了错:
在XXXX表中插入违反了主键唯一性

这好办了,检查这个发布的表设置,发现pre_creation_cmd居然是"none",这怎么行,改为"drop",

try again...

一切ok!

sql server2000的数据同步实在是麻烦不断,因为完全是使用存储过程触发器实现的,弄得很像第三方的一个addon,没有在设计时就在内核集成支持,导致很多时候错误莫名其妙,上次还有一次是因为无法保证长时间不断的连接,导致无法初始化订阅,但报的错误毫无帮助,后来在重起服务器和路由器之后解决。
昨天晚上,在升级程序时,有一条SQL语句执行出错,报错为:
连接中断

当时晕了半天,怎么会连接中断,我在查询分析器里执行的啊,后来用
dbcc checkdb检查

出现一大堆的一致性错误
在用dbcc checkdb检查时,错误信息如下:
服务器: 讯息 8966,层级 16,状态 1,行 1
无法使用闩类型 SH 来读取和闩住分页 (1:3460)。sysindexes 失败。
英文的大致为:
Msg 8966, Level 16, State 5, Server 01AW01, Procedure , Line 3
[Microsoft][ODBC SQL Server Driver][SQL Server]Could not read and latch page
(1:177936) with latch type SH. PFS failed.

(因为我那个毁坏的数据库都无法再attach了,所以上面的错误是我再通过google查出来的)

以下忽略了我的尝试,痛苦,彷徨,为具体的修复过程,因为我这个是一个订阅数据库,所以如果所有方法都不行的话,我只能重建数据库再从DataCenter(Publisher)中把数据导过来,因为这个是单向的合并更新,所以如果导过来,是需要非常多的where语句的

直接truncate table那个无法操作的表,因为这个表数据不重要

尝试:
sp_dboption 'xxxxx','single user','true'
dbcc check db REPAIR_REBUILD

无效

取消订阅,将数据库中的配置修改为维护状态,防止应用程序继续对数据库操作,这个是我自己的配置,和数据库无关

取消订阅后,导致服务器clean subscriber时访问了不一致的数据,数据库变成suspect状态,并且连表都无法查看了

想赶紧停止服务,先备份数据库文件

失败,mdf文件无法支持copy了,CRC校验失败

后悔+伤心.....

google 查找置状态的SQL
UPDATE sysdatabases SET status = status ^ 32768 WHERE name = ...
...

阅读全文...

数据同步订阅的注意事项

[ 2006-05-29 11:48:34 | 作者: progame ]
1、当你可以顺利建立订阅,但是在初始化同步时总是报错:
Error info : number 14010

Full error message : The remote server is not defined as a subscription
server.

那么你首先要查的就是
select @@servername
select SERVERPROPERTY('ServerName')

如果发现不一致,那么就
sp_dropserver 'old_name'
go
sp_addserver 'new_name', 'local'
go

2、如果初始化同步时总提报错说
Error: "The process could not make a generation at the 'Subscriber'

The merge process
timed out while executing a query.Reconfigure the
QueryTimeout parameter and retry the operation

然后你跑到run agent的property中加上 -QueryTimerout 10000
再试 结果还是这个错误的话

那么你就应该试试,重启subscriber的server服务了
因为很有可能有未释放的死锁或进程访问导致无法合并复制无法更新表结构

3、当碰到这个错误时
The agent is suspect. No response within last 10 minutes.

这个表示agent无法忍受这么慢的反应了[code]Just right click the Replication Monitor node, click Refresh Rate
and Settings, and then increase the Inactivity Threshold values.

4、清除订阅端的meta date
EXECUTE [TEST_B].dbo.sp_mergesubscription_cleanup
[/code]...

阅读全文...

sql server 合并复制(Merge Replication)

[ 2006-04-23 22:46:08 | 作者: progame ]
sql server的复制(replication)真是会让人头疼,尤其是数据结构改变后的同步

先说一下如何单向同步,在代理属性中第二步的run agent中通过加命令参数exchangetype来改变,1为uploading,表示只从订阅者上传到发布者,2为downloading,表示只从发布者更新到订阅者,3为bidirectional,表示双向同步,即默认的同步方式。

如果在数据库结构改变后继续同步,可以使用取消同步之前生成的sql脚本一次运行(但我怀疑这样是有问题的),前提是包括订阅脚本一起运行,否则的话就必须在订阅时选择初始化结构和数据,因为不然的话,会报说发布的数据库中没有唯一的rowguidcol,我就奇怪了,为什么不能在没有任何订阅者的情况下做一个快照,这样的话就会自动添加这个列了。

因为我们更新数据库结构时,会将rowguidcol这个列给删除的,这样就导致我下一次再建立同步时又得初始化所有的订阅者,然而我并不希望publisher的数据都更新到subscriber,使用行过滤的办法的话我又得对每个subscriber做不同的发布,这真是一个难题。

解决方法,在建立数据库时,添加属性rowguidcol的列,并且设置唯一性索引,在订阅时,选择订阅数据库已有架构和数据,这样就不会把订阅端的数据冲掉了,但前提是publisher和subscriber的对应同一主键的rowguidcol的值要一样,否则更新时会导致冲突。
1