今天测试Replication遇到下面的错误:
The row was not found at the Subscriber when applying the replicatedcommand.(Source: MSSQLServer, Error number: 20598)
if @@trancount > 0 rollback tran
(Transaction sequence number: 0x0000004100000162000400000000, Command ID: 1)
这个错误说明了当发布服务器上执行的语句在订阅服务器上执行时无法在订阅服务器找到对应的数据,所以出错。在默认情况下,发布代理遇到错误时就会停止,所以后影响后面的发布执行。
解决这个问题的根本原因首先要查出那些数据不同步,可以使用DATADIFF工具验证两边数据,然后同步数据(或者重新初始化)。
查询是哪个Article出了问题可以使用下面的语句:
USE [distribution]
select * from dbo . MSarticles
where article_idIN(SELECT Article_id from MSrepl_commands
where xact_seqno= 0x0000004100000162000400000000)
结果如下(这个例子test表数据有问题):
但是发现那些数据不同步可能会花比较长的时间,为了能够让发布尽快同步,我们可以跳过事务复制中的错误。对于事务复制,有两种方法可以跳过在分发过程中遇到的错误:
· 分发代理的-SkipErrors参数,可用来跳过某种类型的错误。有错误的事务将不提交,但后续的事务将提交。
· sp_setsubscriptionxactseqno存储过程,可用来跳过一个或多个导致错误的事务。非SQL Server的订阅服务器没有此选项。
使用-SkipErrors参数,可以让代理将错误记录下来,而Agent继续运行。通常的做法是在DistributionAgent profile中使用“ Continue On Data ConsistencyErrors”。如图:
注意:代理参数更改将在下次启动代理时生效。如果代理连续运行,您必须停止并重新启动代理。
更多详细信息参考:SkippingErrors in Transactional Replication:http://technet.microsoft.com/en-us/library/ms151331(v=sql.105).aspx
官方文档地址:http://docs.mongodb.org/manual/applications/delete/
删除
在数据库的四种基本操作中,删除操作是指从MongoDB的聚集中删除文档的操作!
概述
mongo shell中的remove()方法为我们提供了这项功能,而且在driver中也是类似的!
注意:对于下列的driver versions中,所有的写操作都要通过getlastError操作来来确定
写操作的结果:
C#, version 0.7
Java, version 2.10.0
Node.js, version 1.2
Perl, version 0.601.1
PHP, version 1.4
Python, version 2.4
Ruby, version 1.8
删除
使用remove()方法从聚集中删除一个文档,remove()方法有如下句法:
db.collection.remove( <query>,<justOne> )
SQL中类似的操作:remove()方法类似于DELETE子句,而且:
1.<query>参数类似于WHERE子句,而且:
2.<justOne>参数采用给一个boolean值而且和LIMIT 1的功能是一样的。
remove()会从聚集中删除文档,如果你没有指定,<query>参数,remove()方法会删除聚集中的全部
文档,但是不会删除聚集中的indexs(索引)!
注意:对于大量的删除操作,先将你要删除的聚集中你想保留的数据复制到一个新的集合中,然后
在要删除的文档上进行drop()操作会更高效!
通过下面的示例阐述了remove()方法的使用:
1.如果有<query>参数,remove()方法会删除所有匹配<query>参数的文档!
下面的操作删除了bios聚集中所有子文档name的first字段的值以字母G开头的文档:
db.bios.remove( {'name.first' : /^G/} )
2.如果有<query>参数,并且将<justOne>参数设置为true或1,remove()方法只会删除匹配的第一个文档!
下面的操作删除了一个文档,该文档的turing字段的值为true:
db.bios.remove( {turing:ture},1 )
3.如果没有<query>参数,remove()方法会删除聚集中的所有文档!
下面的操作删除了bios聚集中所有的文档:
db.bios.remove()
注意:remove()方法与drop()方法不是等价的!
如果要删除聚集中的全部文档,这样做会更快:直接drop掉整个聚集,这样会连同indexes一起删除,然后再
重建聚集和indexes!
Capped Collection
不能再一个Capped Collection上使用remove()方法
隔离
如果<query>参数在聚集中匹配到了多个文档,删除操作也许会与该聚集上的其他写操作交错进行。
对于一个独立的聚集,你可以使用$isolated 隔离操作符来改变上述remove()的行为,这样可以有效
的将remove()操作与其他的写操作隔离开。在<query>参数中使用$isolated :1来进行隔离:
db.bios.remove( { turing:true,$isolated:1 } )
官方文档地址:http://docs.mongodb.org/manual/applications/update/
更新
在数据库的四种基本操作中,更新操作是指那些在MongoDB聚集中修改现有记录或文档的操作。
修改操作用来修改聚集中已经存在的一个或多个文档。MongoDB提供了如下的方式来进行更新操作:
1.update
2.save
注意:仔细思考MongoDB中的update操作的下列行为:
1.当更新操作是的目标文档大小超出了文档原来的大小的时候,更新操作会
在磁盘上重新迁移文档,并且会影响到字段的顺序,这依赖于更新操作的类型!
2.对于如下的驱动版本,所有的写操作都会发出一个getLastError命令,来确认
写操作的结果!
C#, version 0.7
Java, version 2.10.0
Node.js, version 1.2
Perl, version 0.601.1
PHP, version 1.4
Python, version 2.4
Ruby, version 1.8
更新
update()方法是用来修改MongoDB聚集中文档的基础方法。默认情况下,update()方法更新一个文档,
如果使用了multi 操作,update()方法会更新聚集中所有符合query标准的文档。update()方法既可以
用新文档替换现有的文档,也可以对现有文档的指定字段进行修改。
update()方法有如下句法:
db.collection.update( <query>,<update>,<options> )
SQL中类似的操作:update()方法类似于SQL 中的UPDATE子句,并且:
1.<query>参数类似于WHERE子句,并且:
2.<update>参数类似于SET子句。
默认的update()方法更新一条文档类似于SQL中带有LIMIT 1子句的UPDATE。
带有multi操作的update方法类似于SQL中没有LIMIT限制的UPDATE子句!
通过下面的示例来思考update()方法的使用:
1.如果<update>参数只包含更新操作如:$set操作符,update()方法会更新类似的字段,如果要
更新子文档中的字段可以通过.操作符。
下面的操作查询了bios聚集的所有文档中_id字段等于1的文档的子文档name中maddle字段值为
Warner并且在awards字段中添加一个新元素。
db.bios.update(
{ _id: 1 },
{
$set: { 'name.middle': 'Warner' },
$push: { awards: { award: 'IBM Fellow', year: 1963, by: 'IBM' } }
}
)
2.如果<update>参数包含$unset操作,update()方法会将其中包含的字段从文档中移除。
下面的操作查询了bios聚集的文档中第一个_id字段等于3的文档,并且移除例如该文档的
birth字段:
db.bios.update(
{ _id: 3 },
{ $unset: { birth: 1 } }
)
3.如果<update>参数包含的字段并不存在于当前文档中,update()会把这些字段添加到当前文档
中。
下面的操作查询了bios聚集的文档中第一个拥有_id等于3的文档,而且在该文档的添加了mnranch字段以及子文档name中
添加了一个aka的字段:
db.bios.update(
{ _id: 3 },
{ $set: {
mbranch: 'Navy',
'name.aka': 'Amazing Grace'
}
}
)
4.如果<update>参数只包含字段和值的pairs,update()方法会利用<update>参数中的文档对象替换当前文档中
除了_id字段以外的全部字段。
下面的操作查询了bios聚集中第一个name字段等于{ first: 'John', last: 'McCarthy' } 的文档,并且利用
<update>中的文档替换了该文档除_id字段之外的所有字段:
db.bios.update(
{ name: { first: 'John', last: 'McCarthy' } },
{ name: { first: 'Ken', last: 'Iverson' },
born: new Date('Dec 17, 1941'),
died: new Date('Oct 19, 2004'),
contribs: [ 'APL', 'J' ],
awards: [
{ award: 'Turing Award',
year: 1979,
by: 'ACM' },
{ award: 'Harry H. Goode Memorial Award',
year: 1975,
by: 'IEEE Computer Society' },
{ award: 'IBM Fellow',
year: 1970,
by: 'IBM' }
]
}
)
5.如果update操作要求更新一个数组字段中的元素:
1.update()方法会通过调用该元素的下表于.操作符来进行更新。
MongoDB中的数组下表是从0开始的!
2.下面的操作将bios聚集中_id字段为1的文档的contribs数组字段的第二个元素进行了更新:
db.bios.update(
{ _id: 1 },
{ $set: { 'contribs.1': 'ALGOL 58' } }
)
3.update()方法可以在目标数组字段的下标未知的情况下通过$操作符来更新。数组字段必须必须出现在quer参数中,
以便于update()方法决定对那个数组元素进行更新.
下面的操作将更新bios聚集中_id字段等于3的文档的contribs数组字段中包含“complier“的字段,如果找到,update()
方法会将第