MongoDB提供了写关注,用来描述数据库写操做返回信息的保证级别。写关注的强度决定了保证的级别。当插入,更新,删除是弱写关注的时候,操做返回的速度则快。若是写关注是弱的,在一些写失败的时候,写操做可能不会持久。写关注级别越强,客户端则须要越长的时间来等待MongoDB确认写操做。mongodb
MongoDB提供了不一样的写关注的级别来更好的知足不一样应用程序的需求。在一个实际的MongoDB部署中,客户端须要调整写关注的级别来确保重要写操做的持久性。对于其余一些不那么重要的写操做,客户端须要调整到弱写关注来保证更好的性能。数据库
MongoDB定义了以下四种写关注级别,依次从弱到强:网络
实际应用中通常是在Client Driver里设置写关注的,它和db.getLastError()方法关系很大。通常来讲,Mongo Driver在执行一个写操做(insert,update,delete)以后,都会马上调用db.getLastError()命令。这样才有机会知道刚才的写操做是否成功,若是捕获到错误,就能够进行相应的处理。MongoDB Server并不关心错误,只负责通知Client发生了错误。app
这里有2点须要注意:函数
在这种写关注级别时,MongoDB马上返回结果,而后执行写入操做,相似于忽略写错误。然而,驱动程序会去接收和处理网络错误。因此getLastError()的返回值必定是null,即便以后的Apply发生了错误,Driver也不知道。使用这个级别的Write Concern,Driver的写入调用马上返回,因此性能是最好的,可是可靠性是最差的,所以并不推荐使用。在各平台最新版本的Driver中,也再也不以0做为默认级别。其实还有一个w:-1的级别,是error ignored,基本上和w:0差很少。区别在于,w:-1不会捕获任何错误,而w:0能够捕获network error。性能
在这种写关注级别时,mongod确认写操做,而且在内存视图上完成数据改变。它容许客户端捕获网络,重复键等其它错误。和Unacknowledged的区别是,如今MongoDB只有在Apply(实际写入操做)完成以后,才会返回getLastError()的响应。因此若是写入时发生错误,Driver就能捕获到,并进行处理。这个级别的Write Concern具有基本可靠性。可是Acknowledged级别的写关注并不确保数据已经持久化到系统硬盘,它是MongoDB默认的写关注级别。日志
Acknowledged级别的Write Concern也不是绝对可靠的。由于MongoDB的Apply操做是将数据写入内存,按期经过fsync写入硬盘。若是在Apply以后,fsync以前mongod挂了,或者甚至Server挂了,那持久化其实是失败的。可是在w:1的级别下,Driver没法捕获到这种状况下的error,由于response在Apply以后就已经返回到Driver。MongoDB解决这个问题的办法是使用Journal机制,写操做在写入内存以后,还会写到journal文件中,这样若是mongod非正常down掉,重启之后就能够根据journal文件中的内容,来还原写操做。code
在Driver层面,则是除了设置w:1以外,再设置journal:true或j:true,来捕获这个状况下的error。在这种关注级别下,MongoDB能确保写操做将数据提交到了 journal
日志。这种写关注能保证MongoDB崩溃后恢复数据。固然,前提是你必须开启journal
日志功能。但这样写操做必须等到下一第二天志提交才返回结果,为了减小操做延迟,要提升日志提交的频率配置。server
这个写关注级别下,只有Secondary从Primary完成了复制以后,getLastError()的结果才会返回。也能够同时设置journal:true或j:true,则还要等journal写入也成功后才会返回。可是注意,只要Primary的journal写入就会返回,而不须要等待Secondary的journal也写入。相似的也能够设置w:3,表示至少要有3个节点有数据;或者w:majority,表示>1/2的节点有数据。通常小规模的集群就是3节点部署,因此配置w:2就能够了。内存
设置Write Concern级别,其实就是在写操做的性能和可靠性之间作权衡。写操做的等待时间越长,可靠性就越好。对于非关键数据,建议使用默认的w:1就能够了,对于关键数据,则使用w:1 & j:true比较好。这里要注意,journal不管如何都是建议打开的,设置j:true,只是说Driver调用getLastError()以后是否要等待journal写入完成再返回。并非说不设置j:true就关闭了server端的journal。
通常来讲,开发者写的代码,不须要自行调用db.getLastError()函数,Driver在每个写操做以后,都会马上自动调用该方法。
db.collection("test", {}, function(err, collection) { collection.insert({ name: "world peace" }, function(err, result) { assert.equal(null, err); console.log(result); db.close(); }) });
这段代码,driver在insert()以后,隐式调用db.getLastError(),若是捕获到任何错误,就会赋给回调函数中的err参数。区别就在因而否可以捕获到错误。在w:-1时,err永远是null(没有机会捕获到error);在w:0时,通常也捕获不到,除了network error;在w:1时,若是mongod apply发生错误,就会传递给err参数了。代码都是同样的,区别就在于设置的Write Concern级别。详细的说明请参考http://docs.mongodb.org/manual/reference/command/getLastError/。