Mongodb通过GetLastError命令写入安全机制

一、简介

很多人抱怨mongodb是内存数据库,也没有事务,会不安全,其实这都是对Mongodb的误解,Mongodb有完整的redolog,binlog和持久化机制,不必太担心数据丢失问题。

journal是Mongodb中的redo log,而Oplog则是负责复制的binlog(对应Mysql)。

在google.groupuser上,mongo的开发者有一段这样的解释:

#########
By default:
Collection data (including oplog) is fsynced to disk every 60 seconds.
Write operations are fsynced to journal file every 100 milliseconds.
Note, oplog is available right away in memory for slaves to read. Oplog is a capped collection
so a new oplog is never created, old data just rolls off.
GetLastError with params:
(no params) = return after data updated in memory.
fsync: true:
with –journal = wait for next fsync to journal file (up to 100 milliseconds);
without –journal = force fsync of collection data to disk then return.
w: 2 = wait for data to be updated in memory on at least two replicas.
########

可以看到:

1、如果打开journal,那么即使断电也只会丢失100ms的数据,这对大多数应用来说都可以容忍了。从1.9.2+,mongodb都会默认打开journal功能,以确保数据安全。而且journal的刷新时间是可以改变的,2-300ms的范围,使用 –journalCommitInterval 命令。

2、Oplog和数据刷新到磁盘的时间是60s,对于复制来说,不用等到oplog刷新磁盘,在内存中就可以直接复制到Sencondary节点。

GetLastError Command

getLastError 是Mongodb的一个命令,从名字上看,它好像是取得最后一个error,但其实它是Mongodb的一种客户端阻塞方式。用这个命令来获得写操作是否成功的信息。

getlastError有几个参数:j,w,fsync。在大多数的语言驱动中,这个命令是被包装成writeConcern类,比如java。

二、什么时候使用这个命令:

1、Mongodb的写操作默认是没有任何返回值的,这减少了写操作的等待时间,也就是说,不管有没有写入到磁盘或者有没有遇到错误,它都不会报错。但一般我们是不放心这么做的,这时候就调用getlastError命令,得到返回值。

以java为例,举个例子:当我们为字段建立了一个唯一索引,针对这个字段我们插入两条相同的数据,不设置WriterConcern或者设置WriterConcern.NORMAL模式,这时候即便抛出异常,也不会得到任何错误。insert()函数在java中的返回值是WriteResult类,
WriteResult( CommandResult o , WriteConcern concern ){
        _lastErrorResult = o;
        _lastConcern = concern;
        _lazy = false;
        _port = null;
        _db = null;
    }

这个类实际上包装了getlastError的返回值,但是这时候WriteResult的_lastErrorResult属性实际上是空的。因为dup key错误是server error,只有在WriterConcern.SAFE或更高级别的模式下,才会得到server error。

2、在多线程模式下读写Mongodb的时候,如果这些读写操作是有逻辑顺序的,那么这时候也有必要调用getlasterror命令,用以确保上个操作执行完下个操作才能执行,因为两次执行的连接有可能是不同的。在大多数情况下,我们都会使用连接池去连接mongodb,所以这是需要注意的。

举个例子:我们之前遇到这个异常”The connection may have been used since this write, cannot obtain a result”,异常原因有两个,连接池数量太小,竞争太激烈,没有设置writerConcern.SAFE。
参见:https://groups.google.com/forum/?fromgroups=#!topic/mongodb-user/xzw0Cb831VY
PS:在java等语言中,是不需要显示调用这个命令的,只需要设置WriterConcern即可。

三、getlastError最佳实践

1、如果没有特殊要求,最低级别也要使用WriterConcern.SAFE,即w=1。

2、对于不重要的数据,比如log日志,可以使用WriterConcern.NONE或者WriterConcern.NORMAL,即w=-1或者w=0,省去等待网络的时间。

3、对大量的不连续的数据写入,如果每次写入都调用getLastError会降低性能,因为等待网络的时间太长,这种情况下,可以每过N次调用一下getLastError。但是在Shard结构上,这种方式不一定确保之前的写入是成功的。

4、对连续的批量写入(batchs of write),要在批量写入结束的时候调用getlastError,这不仅能确保最后一次写入正确,而且也能确保所有的写入都能到达服务器。如果连续写入上万条记录而不调用getlastError,那么不能确保在同一个TCP socket里所有的写入都成功。这在并发的情况下可能就会有问题。避免这个并发问题,可以参考如何在一个链接(请求)里完成批量操作,URL:java driver concurrency

http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency

5、对数据安全要求非常高的的配置:j=true,w=”majority” db.runCommand({getlasterror:1,j:true,w:’majority’,wtimeout:10000})
java语言可以在MongoOption中设置,MongoOption中的这些设置是全局的,对于单独的一个(连接)操作,还可以分别设置。

参考:
1、http://www.mongodb.org/display/DOCS/Journaling
2、http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency
3、http://www.mongodb.org/display/DOCS/getLastError+Command

时间: 2024-10-28 22:05:18

Mongodb通过GetLastError命令写入安全机制的相关文章

mongoDB 3.0创建访问控制权限的方法及Mongodb GetLastError写入安全机制

mongoDB 3.0 安全权限访问控制 mongoDB 3.0 访问控制改了很多,需要注意这个参数authenticationMechanisms.为了兼用2.6版本,我直接指定下面的参数: setParameter:  authenticationMechanisms: MONGODB-CRParameter:  authenticationMechanisms: MONGODB-CR 下面看看如何创建访问控制权限 不使用 -auth 参数,启动 mongoDB mongodb-<a hre

MongoDB 生态 - 官方命令行工具

工欲善其事,必先利其器,我们在使用数据库时,通常需要各种工具的支持来提高效率:很多新用户在刚接触 MongoDB 时,遇到的问题是『不知道有哪些现成的工具可以使用』,本系列文章将主要介绍 MongoDB 生态在工具.driver.可视化管理等方面的支持情况. 本文主要介绍 MongoDB 官方的命令行工具 Mongo shell MongoDB 的命令行管理工具,也是 MongoDB 最常用的工具,功能非常丰富,比如常用的 show dbs / show tables / show users

mongodb与mysql命令对比

mongodb与mysql命令对比 传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由数据库(database).集合(collection).文档对象(document)三个层次组成.MongoDB对于关系型数据库里的表,但是集合中没有列.行和关系概念,这体现了模式自由的特点.  MySQL MongoDB 说明 mysqld mongod 服务器守护进程 mysql mongo 客户端工具 mysqldump mong

MongoDB基本管理命令

原文链接: http://blog.csdn.net/shirdrn/article/details/7105539 MongoDB是一个NoSQL数据库系统:一个数据库可以包含多个集合(Collection),每个集合对应于关系数据库中的表:而每个集合中 可以存储一组由列标识的记录,列是可以自由定义的,非常灵活,由一组列标识的实体的集合对应于关系数据库表中的行.下面通过熟悉MongoDB的基本管理 命令,来了解MongoDB提供的DBMS的基本功能和行为. MongoDB命令帮助系统 在安装M

【MongoDB】6.关于MongoDB存储文件的 命令执行+代码执行

参考:http://www.runoob.com/mongodb/mongodb-gridfs.html 1.命令执行 MongoDB GridFS GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片.音频.视频等). GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中. GridFS 可以更好的存储大于16M的文件. GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文

win7 64位下 mongodb安装及命令运行

有网友老催我把框架加上mongodb的支持,于是偶尔抽空看了看相关的文章.   今天有缘,就把mongodb安装了一下,中间遇到了小小的问题,So,把整个过程记录一下: 1:先上官网:http://www.mongodb.org/downloads 下载最新的:   下载完后文件名为:mongodb-win32-x86_64-2.4.6.zip 解压到当你要安装的目录,然后我把目录名给改短了一下,叫mongodb246,放在了e盘下. 2:用cmd运行目录下bin下的mongod.exe来安装服

MongoDB中使用的SCRAM-SHA1认证机制

介绍 SCRAM是密码学中的一种认证机制,全称Salted Challenge Response Authentication Mechanism. SCRAM适用于使用基于『用户名:密码』这种简单认证模型的连接协议. SCRAM是一个抽象的机制,在其设计中需要用到一个哈希函数,这个哈希函数是客户端和服务端协商好的,包含在具体的机制名称中.比如SCRAM-SHA1,使用SHA1作为其哈希函数. 前言 基于『用户名:密码』这种简单认证模型的协议中,客户端和服务端都知道一个用户名(username)

利用MongoDB的SplitVector命令实现并发数据迁移

背景 数据迁移是数据库运维中一个很常见的场景.数据迁移分为全量和增量.为了追求速度,通常我们会采用并发的方式对数据进行全量迁移.在全量导出数据时,通常都会选择做到记录级的并发,因此通常会涉及到对需要导出的某个表(集合)按照并发度进行切分(分区)的过程.现有常用做法是通过若干个skip加limit来找到一些分区点,然后就可以并发同时导出多个分区.事实上MongoDB还有一个SplitVector命令特别适合用来做集合的分区.本文将介绍一下如何利用这个命令来对集合做分区,实现并发数据迁移. 命令简介

MongoDB模糊查询命令

命令行查询: 1.可以使用 .* 来模糊查询,如下是查询姓陈的用户. db.customers.find( { name : /陈.*/i } );   2.也可不带*号 db.fs.files.find({filename:/install_mongo.sh/i}) PHP查询: $query=array("name"=>newMongoRegex("/.*".$name.".*/i")); $db->find($query); 简