Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作
Mongodb Manual阅读笔记:CH3 数据模型(Data Models)
Mongodb Manual阅读笔记:CH4 管理
Mongodb Manual阅读笔记:CH5 安全性
Mongodb Manual阅读笔记:CH6 聚合
Mongodb Manual阅读笔记:CH7 索引
Mongodb Manual阅读笔记:CH8 复制集
Mongodb Manual阅读笔记:CH9 Sharding
4.1.3.2 使用Capped Collection做先入先出
4.2.1.6 管理日志(同mysql bin-log,sql server的事务日志)
本节介绍操作mongodb的策略和实践
主要介绍1,Mongodb系统的备份策略,2.Mongodb的监控,3.在线配置,4.导入导出
5.注意点
备份可以让数据保持一致性和可用性,并测试备份保证备份的可用。
1.在位子上,要和主库分开
2.系统错误,当出现硬件错误或者磁盘错误是,可以从备份中成功恢复
3.生产环境约束,备份操作有时会要求大量的系统资源,所以要和业务高峰分开,避免影响
4.系统兼容性,如一些block-level快照工具需要支持的系统或者一些基础设备
5.数据库配置,复制集和shard会影响备份的实现
6.实际的需求,对重要数据和不重要数据区别对待
备份方法分为2种:
1.二进制方式的备份,使用mongodbdump工具对数据库进行dump,但是不能抓取到某个时间点的备份。
2.创建文件系统镜像,有时候会使用block level备份,会产生比较大的备份,但是快速,可以体现某个时间点的备份。
备份的选择依赖于部署和容灾恢复的需要。
对于某些场景来说,备份是很困难的或者不太可能的,因为数据量很大,又是分布式的,这样的情况下,可以考虑增加复制集。
Shard集群备份考虑:对于shard集群来说抓取某个点的数据,必须停止所有的写入,不然抓取的只可能是近似某个时间点的快照。你可以备份shard的复制集的secondary的近似某个点的备份,前提是应用可以接受近视某个点的数据。
复制集备份考虑:复制集备份2个方案:
1.在secondary上创建一个快照,然后备份,当然也可以创建一个隐藏的成员专门用于
2.也可以使用mongodump程序使用 --oplog来备份,用mongorestore程序--oplogReplay 来恢复。
如果在shard下,每个shard都是一个复制集,可以备份某个成员来完成,但是还是要关闭均衡器。在secondary上创建备份可以不影响primary性能。
主要介绍一些监控方法和一些监控工具
有3种方法收集当前mongodb的状态:
1.使用和mongodb一起发布的试试报表
2.使用数据库命令,获取当先数据库的状态
3.使用MMS mongodb 监控服务,收集Mongodb信息,提供可视化的,和一些告警,目前是免费的。
工具:Mongodb发布时带了一些报告工具,Mongostat,mongotop,
REST接口:mongodb提供了一个REST接口,可以用来配置监控,和设置告警,要开启要带上启动参数--rest或者在配置文件上面rest=true
HTTP 命令行:mongodb提供web版命令行,可以数据localhost:<port>这个端口是mongod端口加1000。
mongodb还提供了一些命令开报告数据库当前状态。
serverStatus:serverStatus或者db.serverStatus()可以看数据库当前状态,这个命令一般不直接运行,一般是通过统计
dbStatus:dbStats或者db.stats()范围当前存储的使用,监控指定数据库的状态,存储能力
collstats:collStats提供Collection级别的一些信息
replSetGetStatus:replSetGetStatus命令也可以使用rs.status(),查看大概的复制集的状态,使用这个数据确保复制是否配置,并检查host和复制集的状态
有一些开源的工具,可以看手册p140,还有就是SaaS服务。
mongod和mongos会记录所有的服务状态到标准输出或者日志文件中有一些配置参数:
1.quite. 限制大量信息被写入到日志或者标准输出
2.verbose.增加大量信息写入到日志或者输出
3.logpath.写入到日志文件
4.logappend.增加信息到已有文件中,而不是覆盖。
有2个命令会影响日志:
1.getLog.输出当前进程日志
2.logRotate.切换日志
性能降低往往和数据量,内存,连接数,锁定时间有关。性能问题涉及,负荷,访问方式,可用资源,索引设计,甚至程序设计。
锁:mongodb使用锁来保证数据的可用性,如果serverStatus输出中globalLock.currentQueue.total一直很高,那么说明又大量请求在等待这个锁,说明是并发引起的问题。
globalLock.totaltime相当于服务启动时间,gobalLoc.radio=locktime/totaltime,比例越高说明被锁定的时间越长,可能是慢查询,系统结构问题,或者内存不够。
内存使用:Mongodb使用文件映射的方式来保存数据,让数据都在内存,这样才能保证数据库较高的性能,serverStatus会输出内存使用的情况,mem.resident如果超过内存系统内存那么表示数据在硬盘而不是在内存。mem.mapped如果这个值大于系统内存,有可能会造成页错误。
页错误:如果mongodb请求数据不再内存中,那么就会发生也错误,要到虚拟文件中加载数据。可以查看serverStatus中的extra_info.page_faults。一个错误页并不是问题,但是出现很多错误页的时候,就表示内存不足,mongodb中发生页错误时,线程会退让,让其他线程先运行以提高并发。
连接数:连接数过大会给服务带来巨大的性能问题,serverStatus提供一下几个关于连接的信息:
1.globalLock.activeClients 包含了活动的客户端总数
2.connections包含2个current当前客户端的总数,available所有未使用的连接的总数
对于包并发的请求,可以根据需求使用读写分离或者shard。
大量固定的连接也可能是驱动的问题,每个驱动都是实现连接池的,大量的连接但是没有被使用就说明驱动或者其他配置有问题。
Database Profiling:Profile可以帮忙记录所有的非有效查询,有3个级别:
1.0表示关闭
2.1表示值抓取slow
3.2表示全部抓取
当配置1时可以使用db.setProfilingLevel()来设置级别也可以用来指定slow阀值。
监控复制集一定要监控复制延迟,有2个问题可能会是复制延迟造成的:
1.若出现延迟,并没有复制到secondary,一旦崩溃就会造成一致性问题
2.如果secondary落后超过了oplog,mongodb会启动重新初始化同步。oplog可以在配置文件中配置,如果不配置使用默认大小,默认所有可用空间的5%。
复制延迟要不就是网络问题,要就是primary资源不足以支持应用。可以通过rs.status(),其中有个值optimeDate反应最后一个项被应用到复制集的时间。
配置服务:配置服务维护了哪些数据是放在哪个shard下面的。shard之间会更新这样的记录,当配置服务不可访问的时候,整个shard操作就不能进行了,已经在访问的不受影响。
所以配置服务不可用是一个很严重的问题。要监控配置服务是否运行正常。
均衡和记录复制:高效的shard集群,会把配置服务器也放在均衡器下,提高配置服务的可用性。
锁过期:在均衡器上使用的锁,当过期之后就会被自动释放,任何长时间的锁都会影响均衡器的性能。可以切换到config数据库,然后使用db.locks.find()查看锁情况。
介绍通用的配置,最佳实践配置的场景,主要通过配置文件为接口,使用--config或者-f 加配置文件。
基本配置参数:
1.fork,如果为true以服务方式运行
2.bind_ip,指定一个ip,表示服务器只侦听这个这个ip
3.port,是指绑定的端口默认为27017
4.quite,为true表示大多数信息都不写入日志文件,可以在在线的时候用setParameter修改
5.logpath,指定mongod进程日志输出位置
6.logappend,为true追加到文件中,而不是覆盖
7.journal,为true表中写入操作的可持久性
1.bind_ip,可以配置多个用逗号隔开,只允许这些ip访问
2.nounixsocket,为true禁用unix socket,默认为可用
3.auth,为true,开启mongodb认证系统,要创建用户认证信息
复制配置:复制很简单,只要设置replSet=set0,通过设置keyFile启动复制集认证。设置keyFile启动认证并且指定一个key file对应复制集成员的使用。
Shard配置:configsvr=true表示创建一个config 服务,运行在bind_ip的port上,shardsvr配置shard服务,shard还要配置configdb,通过chunkSize修改chunk大小,但是不建议修改。
dbpath,指定数据库文件夹位置,padfilepath指定mongod的进程id文件。
1.slowms用于配置数据库profile slow阀值
2.profile 设置profiler级别,
3.verbose 启动verbose日志模式,mongod输出和增加日志的事件。verbose一般只在看不出问题的时候使用,v=ture表示启动verbose,每增加一个v表示额外的日志。
4.diaglog,启动争端日志,Level 3记录所有的读取和写入
5.objcheck,强制mongod验证所有从客户端的执回
6.cpu,强制mongod报告,最后一个间隔花在write lock上面的比例,这个间隔通常是4s
JSON不支持BSON很多数据类型,当decode BSON文档到JSON会造成一些精度丢失
不管你决定如何导入导出数据,考虑一下几条:
1.标记文件制定什么时候启动的备份
2.标记标记可以描述备份的上下文那些数据备份了
3.如果对备份有不利影响时,不要启动导出
4.保证能够反映数据一致性
5.通过恢复和导入,测试备份和导出
可以使用copydb,clone,cloneCollection命令,mongo提供db.copyDatabase()方法。
使用mongoexport导出Collection : mongpexport --collection collection --out collection.json。
默认可以使用--jsonArray导出json数组,--csv导出csv。如果没有开mongod可以指定数据库文件。被指定数据库文件后,文件会被锁定,mongod不能附加这些文件。
使用mongoimport导入Collection:格式和导出类似,可以指定--upsert表示会试图更新已有的文档。还可以使用--journal指定生产日志。
MongoDB:一般都使用64bit,对于32bit,mongodb可以用于测试开发环境,并不适合产品部署,但是不能保存大于2GB数据。
操作系统:mongodb目前支持,MAC OS X,Linux,Windows Server 2008 R2,Windows7
每个数据库都有一个读写锁。
MongoDB使用顺序写入的方式写入到磁盘来保证数据操作的持久性。为了保证crash后可用,你可以启动journal。
使用信任的网络环境:默认mongo不启动认证,认为环境是可信任的。如果是敏感的系统可以指定只被某些服务器访问。
连接池:为了避免连接占用过大资源,应该注意连接池的大小。
配置足够的CPU和内存:cpu对于数据库来说没有很大的需求,因为数据库不是cpu密集型的,但是对于内存来说是比较重要的。
使用SSD硬盘:SSD硬盘在随机读写上面的性能很出色,可以很好的提高随机io性能
避免使用远程文件系统:这会给Mongo带来性能问题
NUMA硬件:在linux 上,NUMA会给mongo带来一些性能问题,应该禁用NUMA。禁用方法:
numactl --interleave=all /usr/bin/local/mongod
echo 0 > /proc/sys/vm/zone_reclaim_mode
SWAP:分配足够的空间,避免出现内存争用现象,对于mongod来说数据映射的,都是并不会被放到swap中
RAID:IO密集型,建议选择RAID10
远程文件系统:并不建议使用远程文件系统,当数据和日志放在同一个NFS的时候会出现性能问题,如果非要用,可以考虑把日志放在iscsi数据房子啊NFS中
分别存储:可以考虑把数据,日志,和进程日志分开存放到不同存储上以提高io性能。
Write Concern:Write Concern保证了Mongodb写入安全性。可以根据不同的数据划分write Concern。
复制集:看p390
shard集群:看p502
内核和文件系统:mongodb可以在使用大文件之前,预先分配数据库文件,所以你要使用ext4和xfs文件系统。ext4至少内核要2.6.23,xfs内核至少要2.6.25.
推荐配置:
1.关闭数据库文件所在的存储卷的atime
2.设置描述符限制(-n)和用户进程限制(-u)
3.不要使用hugepages虚拟内存地址
4.关闭NUMA
5.确保预读设置比较适合
6.使用NTP(Nwtwork Time Protocol)来同步时间
虚拟环境:mongodb可以在EC2,VMWare,OpenVZ上运行
iostat: linux上用于检查次磁盘io的工具
bwm-ng:命令行命令用户监控网络的使用
查看p136页,关于备份的策略
数据管理包括,多数据中心部署,管理大文件存储,数据生命周期工具
mongodb可以通过函数参数来隔离,确定mongod实例是用户report的工作负荷,还是用于高频率shard的一部分
概述:mongodb可以通过方法或者地理位置隔离应用程序操作。
这个能力允许应用程序通过地理位置的不同来考虑mongodb的部署,mongodb可以更具操作的不同来区分,可能被区分到不停的地理位置的不同的数据中心。你可以:
1.保证写入操作只传播到特定的复制集的成员
2.指定特定的复制集成员来响应数据读取
3.确保特定的shard key对于到指定的shard上
4.可以整个以上特性到一个复制部署上
具体请看:
读偏好,从那个复制成员上面读数据
写注意(write Concern),控制写操作广播到几个成员
复制集tags,用于创建用户化的读取偏好和write concern
Tag Aware Sharding,用于指定均衡策略
Capped Collection是一个环形buffer,新的数据会覆盖最老的数据。
Capped Collection有一下好处:
1.保证插入的顺序
2.只能更新,更新前后文档大小一样的。
3.自动删除最好的数据
使用场景:
1.保存高层生成的日志
2.保存小量的数据
1.可以插入后更新,但是更新不能让文档增长
2.不能删除
3.不能shard
4.默认在_id上有个索引
5.使用自然顺序,有效的从collection读取数据
可以使用createCollection()创建capped collection如:
db.createCollection( "log", { capped: true, size: 100000 } )
db.createCollection("log", { capped : true, size : 5242880, max : 5000 } )
查询Capped Collection:使用find()查询,用sort排序。
转化成Collection:可以通过convertToCapped命令把capped Collection转化为普通Collection。
到期之后自动删除数据:Mongodb可以创建TTL索引,允许你删除过期数据。
Tailable Cursor:你可以使用Tailable Cursor连续取回数据,用于capped collection
TTL Collection过期后数据会自动删除,TTL依赖于后台的线程,读取时间类型的值,并且删除过期数据。
使用ensureIndex()创建一个TTL索引来启动TTL 功能,创建后即可启动,过期数据的删除可以使用db.currentOp()或者profile查看。
过期数据的指定有2种方法:
1.超过了指定的秒数
2.超过了指定时间
指定秒数:
db.log.events.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )
指定时间:
db.app.events.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
在创建TTL Collection时需要一个时间字段,在创建索引是指定这个时间字段即可。
1._id字段在TTL索引中不支持
2.不能再已经有索引的字段创建TTL索引
3.如果索引字段不存在,文档不会过期
4.如果不是BSON日期类型或者不是日期数组类型,不会过期
5.TTL索引不能复合
6.如果TTL域如果是一个时间数组,最小一个过期就算过期
7.不能再capped collection上创建TTL索引
8.不能用ensureIndex()改变过期时间
很多因素都会影响mongodb性能,如查询,索引,数据模型,应用设计,结构和系统配置
直接开启profile然后抓取慢查询,适当调节索引
直接使用db.currentOp()的shell命令
使用explain()返回查询的执行计划,看是否有有效的索引等
Capped Collection是以环形的方式,新数据覆盖老数据的方式,并且空间时固定的,可以又很好的写入性能和顺序读性能。
因为写入都是自然顺序的,按自然顺序读取就会很快。
用索引覆盖查询,以提高查询性能。但是索引也是有写入操作的性能消耗的。查询是顺序还是逆序,都可以利用索引。
减少查询结果,尽量少输出,减少网络需求可以使用limit()
同样是为了减少输出
用hint()强制使用某个索引
使用$inc这样自增操作可以在服务端上运行,可以不用先查询,后修改。
动态Schema:mongodb中schema是动态的,并不强制要求文档结构,虽然collection是保存结构类似的数据。注意点:
1.准确的设置使用的collection
2.只有_id索引是不需要定义的,其他都需要定义
3.选择合适的shard key一旦定义就不能被修改
大小写敏感:Mongodb中字符串是大小写敏感的
类型敏感:如果在字符串的字段上,用数字去搜索是不会返回结果的
1.默认update只影响一行
2.BSON文档大小的限制默认为16MB,若更大可以使用GirdFS
3.没有一般意义上的事务,如果要做事务,需要通过2阶段提交方法,用户自己实现。
1.使用奇数个复制成员,为了保证当选成功要不使用奇数个成员(通常是3个),要不用仲裁
2.保持成员up-to-date,考虑以下方法:
a.使用监控告警复制延迟
b.指定write concern
c.如果你使用手动failover,你可以吧secondary配置成优先级为0
1.配置shard小心,不能为已经shard的collection重新指定shard key
2.shard key不能修改
3.当在已存在的collection上使用shard,mongodb会使用collection中最大的大小来保证创建chunk。
4.shard key要求唯一
5.在大批量导入之前考虑使用预分配
管理教程一步一步的演示如何执行Mongodb的安装,维护和配置。
主要从以下几个方面:
1.配置,维护和分析
a. 管理mongod进程
b. 日志切换
2.备份和还原
a.使用文件系统快照做备份还原
b.备份还原shard集群
3.Mongodb脚本化
4.Mongodb教程
从以下几个介绍:
1.使用数据库命令,2.管理mongod进程,3.分析数据库操作的性能,4.使用SNMP管理Mongodb,5.切换日志文件,6.管理日志,7.保存javascript方法,8.更新mongodb,9.Mongodb教程
mongodb命令接口包含了所有非CRUD的操作。
数据库命令的格式就是BSON格式
使用db.runCommand(BSON格式)就可以使用了
如果要在admin数据库运行一些命令可以使用一下:
use admin
db.runCommand()
对于admin的命令也可以使用一下,会自动应用到admin上下文
db._adminCommand()
所有的命令返回都有一个ok标记不管命令运行是否成功,如果运行失败,ok标记就会返回0。
Mongod进程是主数据库进程运行在独立的服务器上,Mongos提供一些Mongod的服务对客户端透明。
启动mongod:使用命令mongod启动命令
指定特殊目录:使用--dbpath 来指定数据库文件所在的位置
指定TCP端口: 使用--port选项指定
以服务方式启动: --fork指令表明可以以服务方式启动
额外的配置选项:看手册page 145
停止服务:使用shutdownServer()方法,从shell中停止mongod服务,也可以使用mongod --shutdown 来关闭服务。也可以使用ctrl-c,kill命令。
停止复制集:
1.检查备机替换。
2.如果10秒内没有备机,mongod会返回一条消息不回被关闭。
3.如果在10秒有备机,primary会逐步关闭,并等待备机接上。
4.如果60秒后或一旦备机接上,主机就会关闭。
强制复制集关闭:使用db.adminCommand({shutdown:1,force:true})。db.adminCommand({shutdown:1,timeoutSecs:5})(db.shutdownServer({timeoutsecs:5})),也可以指定一个时间,如果在这个时间内备机没接上,就不会关闭。如果接上了就可以关闭。
通过profile就可以抓取每个数据库的操作。并存放在一个capped collection内。
0,关闭profile;1,只抓取slow查询;2,抓取所有数据。
可以通过mongo shell启动,也可以通过驱动中的profile命令启动,启动后记录会被保存在system.profile collection下,可以使用db.setProfilingLevel来启动。默认slow为100 毫秒。db.setProfilingLevel可以有2个参数,第一个参数指定Profiling 级别,第二个参 数指定slow阀值。
检查当前Profiling 级别:可以通过db.getProfilingStatus()获取当前profiling级别,slowms 标记慢查询阀值。
关闭Profiling:还是使用db.setProfilingLevel(0)来关闭profiling
整个实例开启Profiling:mongod --prifile=1 --slowms=15
shard的Profiling:对shard的profiling要对每一个实例进行profiling
可以直接在system.profile的collection上查看如:db.systen.profile.find()。或者使用show profile,会显示最近至少1ms时间运行的前5条记录。
要修改system.profile collection的大小必须:1.关闭profiling,2.删除system.profile,3.然后重新创建system.profile,4.重启profile。
shell如下:db.setProfilingLevel(0)
,db.system.profile.drop()
,db.createCollect("system.profile",{cappedLtrue,size:4000000})
,db.setProfilingLevel(1)
这个功能只有在企业版中可用:www.mongodb.com/products/mongodb-enterprise
安装版本:企业版
包含文件:1.MONGO-MIB.txt这个文件包含了mongodb的SNMP输出。2.mongod.conf,SNMP的配置文件,用来配置SNMP的公有名称,权限,访问权限等。
要求的包:
1.Ubuntu 11.04 要求libssl0.9.8, snmp-mibs-downloader, snmp, 和 snmpd. 使用如下命令: sudo apt-get install libssl0.9.8 snmp snmpd snmp-mibs-downloader
2.Red Hat Enterprise Linux 6.x series和Amazon Linux AMI 要求 libssl, net-snmp,net-snmp-libs,和net-snmp-utils.使用如下命令:sudo yum install libssl net-snmp net-snmp-libs net-snmp-utils
3.SUSE Enterprise Linux 要求 libopenssl0_9_8, libsnmp15, slessp1-libsnmp15, andsnmp-mibs.使用如下命令:sudo zypper install libopenssl0_9_8 libsnmp15 slessp1-libsnmp15 snmp-mibs
安装MIB配置文件:要确保路径/usr/share/snmp/mibs 存在,如果不能保证使用mkdir 创建,然后在路径上创建一个MONGO-MIB.txt连接,然后用把配置文件复制到该路径下:
sudo mkdir -p /usr/share/snmp/mibs
sudo ln -s <path>MONGO-MIB.txt /usr/share/snmp/mibs/
cp mongod.conf /etc/snmp/mongod.conf
启动:可以使用mongod --help | grep snmp来抓取和snmp有关的选项。
保证路径/data/db和/var/log/mongodb文件夹存在,然后启动mongod实例,指定snmp选项:
mongod --help | grep snmp
mkdir -p /var/log/mongodb/ /data/db/
mongod --snmp-master --port 3001 --fork --dbpath /data/db/ --logpath /var/log/mongodb/1.log
测试SNMP:检查是否有监听关口1161,使用命令lsof -i <port>或者使用netstat -anp | grep 1161。
本地使用snmpwalk:snmpwalk提供从MIB文件中获取和分析数据的工具。使用如下:
snmpwalk -m MONGO-MIB -v 2c -c mongodb 127.0.0.1:1161 1.3.6.1.4.1.37601
snmpwalk -m /usr/share/snmp/mibs/MONGO-MIB -v 2c -c mongodb 127.0.0.1:1161 1.3.6.1.4.1.37601
出现异常是可以检查:/var/log/mongodb/1.log文件,当出现以下问题的时候表示无法读取配置文件:[SNMPAgent] warning: error starting SNMPAgent as master err:1
日志切换是归档当前的日志,然后重开一个新的,日志文件的切换用UTC时间戳来命名,创建新文件,关闭老文件,把日志写入到新文件中。当mongod或mongos收到SIGUSR1信号或者logRoate命令时,才会被切换。
日志文件切换:
use admin
db.runCommand({logRoate:1})或者kill -SIGUSR1 <mongodb 进程id>
syslog切换:
1.mongod启动要有syslog选项
2.使用系统日志自带的切换方式切换
mongodb使用顺序写的方式保证写操作的持久性和崩溃恢复。在修改数据库文件直线,mongodb会先写入日志,若遇到错误或者崩溃就可以从日志中redo。若没有日志,mongod出现不可预期错误,就要假设你的数据就是不一致的,不许运行数据库修复,或者在复制集中使用数据库同步。若有日志就可以通过日志让数据库回到一致性状态。
如果使用了日志,你又要想把一个数据集放入内存,除了数据占用的内存之外,还需要加入write working set。write working set 是想要在重新映射之间看到的数据差距。
启动日志:在启动mongod的时候加入选项--journall。如果没有日志,当mongod重启的时候,会预先分配这些文件。在创建期间,mongod不会去侦听任何连接。
禁用日志:使用--nojournal命令
获取提交通知:可以通过getLastError命令的j选项来获取通知
避免预分配延迟:如果想要避免预分配延迟,可以先分配,然后复制:
1.创建一个临时文件夹mkdir ~/tmpDbpath
2. 通过mongod启动创建日志文件mongod --port 10000 --dbpath ~/tmpDbpath --journal
3. 当看到以下输出的时候,用ctrl-c关闭服务进程web admin interface listening on port 11000
4. 然后复制这些文件到数据文件夹下mv ~/tmpDbpath/journal /data/db/
5. 重启实例mongod --port 27017 --dbpath /data/db --journal
监控日志状态:可以使用serverStatus命令返回数据库状态中查看,也可以用journalLatencyTest命令查看
获取组提交间隔:可以设置组提交间隔,使用--journalCommitInterval选线,范围在2-300MS之间。
崩溃后恢复数据:当崩溃后重启,mongodb回放这些日志
保存javascript都保存在system.js中,可以使用save命令保存。并且可以使用db.eval(方法)来调用。当然也可以使用db.loadServerScripts()一旦load完之后,就可以直接调用。
在更新前要保证以下几点:
1.保证有最新的备份
2.通过Release Notes和驱动文档,注意兼容性和特殊要求
3.若有复制,要有一个更新维护窗口
4.在生产库上更新之前,现在备用库上使用,确保兼容性等问题。
1.部署认证,先更新mongodb驱动
2.更新shard集群
3.更新standalone实例
4.更新非shard集群的复制集
更新方法有以下2种:
1.使用官方的工具更新 如apt-get
2.直接覆盖已有的二进制文件
1.复制最新版的二进制文件包
2.关闭实例
3.替换
4.起送实例
1.关闭均衡器
2.更新mongos实例
3.独立更新config server,根据config server列表独立启动,为了保证集群online,保证至少有一个config 服务是在运行。
4.更新shard节点,若shard是一个复制集,要用更新复制集一样的 方式更新
5.开启均衡器
更新备份库:
1.更新这个实例
2.然后等待备份库状态,在shell 里面可以使用rs.status()
3.若状态变为了STARTUP2或者RECONVERING,为了保证备份库就绪,状态等到SCEONDARY,然后再继续下一个备份库的更新。
更新主库:
1.让主库进入failover,使用rs.stepDown()或者replSetStepDown命令
2.一旦主库step down,调用rs.status()方法,知道发现被成功转移,其他节点变成primary
3.更新这个实例。
如果在快照备份不可用的情况下,用工具被分是最合理的。
基本mongodump选项:mongodump备份有2中方式:
1.连接到一个mongodb实例
2.直接访问mongodb数据库文件
如果没有参数默认连接到local的27017端口下。
使用oplog指定事件:在复制集中使用--oplog选项收集oplog项来创建一个事件点的快照。然后使用mongorestore --oplogReplay来恢复备份
不使用实例还创建备份:可以直接可以通过--dbpath参数指定数据库文件,不需要连接到实例。
从非本地实例创建备份:直接接入--host和--port就可以连接到远程的实例进行备份,如:
mongodump --host mongodb1.example.net --port 3017 --username user --password pass --out /opt/backup/mongodump-2012-10-24
mongorestore的参数基本和mongodump类似。
还原Oplog备份:还原这个备份是要但是原想 --oplogReplay,也可以考虑加入 --objcheck来检查对象的一致性,加入--drop会在导入前删除数据库中的所有collection
还原数据子集:可以使用--filter 来过滤数据然后到处子集
不用mongod还原:和备份一样可以直接通过--dbpath连接到数据文件,不需要连接到实例。
还原非本地数据:mongorestore --host mongodb1.example.net --port 3017 --username user --password pass /opt/backup/mongodump-2012-10-24
创建完快照之后,你可以mount快照卷,然后把快照里面的数据复制到你的文件系统中,备份就是完全拷贝。快照有一下几个限制:
1.当快照发生时,数据库必须可用,要求所有的写入操作必须被写入到磁盘,要不放到journal要不放到数据库文件。如果不再磁盘上,那么这些修改不会被备份反映。
2.快照是对整个磁盘做image。可以考虑把数据文件放到单独的一个盘上面
3.把快照备份放到其他服务器上保证不会出现单点故障
4.不同的快照有不同的能力,但是lvm方式,不支持增量备份。
带journal的备份:如果有journal,你可以使用任何方式的快照来创建备份
在Amazon EBS的Raid 10配置下的快照:在这个环境下,你不可能伙同快照工具保证一致性,有一下方法:
1.先把写入都写到磁盘上确保一致性,加写锁,然后在备份确保一致性
2.配置lvm运行,让数据文件在raid上面。
创建备份:lvcreate --size 100M --snapshot --name mdb-snap01 /dev/vg0/mongodb
创建了一个快照名字叫做mdb-snap01,这个快照有100MB,这个大小不是数据文件的大小,而是快照和当前状态之间差距的大小。
当命令返回,快照就已经被创建好了,虽然快照备份速度非常快,但是对于备份存放来说快照不是一个很好的方式。因此还需要把这些快照复制出来,进行归档。
归档快照:创建好了快照之后,要mount快照并且把数据放到一个独立的存储上面,如:
umount /dev/vg0/mdb-snap01
dd if=/dev/vg0/mdb-snap01 | gzip > mdb-snap01.gz
先保证是unmount状态,然后使用dd进行复制和压缩
还原快照:
lvcreate --size 1G --name mdb-new vg0
gzip -d -c mdb-snap01.gz | dd of=/dev/vg0/mdb-new
mount /dev/vg0/mdb-new /srv/mongodb
先创建一个逻辑卷,然后制定设备路径,这里指定了1g大小,那么原文件大小必须小于1g。然后解压到这个逻辑卷上,然后把这个逻辑卷mount到/srv/mongodb上。
直接从快照上还原:
umount /dev/vg0/mdb-snap01
lvcreate --size 1G --name mdb-new vg0
dd if=/dev/vg0/mdb-snap01 of=/dev/vg0/mdb-new
mount /dev/vg0/mdb-new /srv/mongodb
远程备份:
umount /dev/vg0/mdb-snap01
dd if=/dev/vg0/mdb-snap01 | ssh [email protected] gzip > /opt/backup/mdb-snap01.gz
lvcreate --size 1G --name mdb-new vg0
ssh [email protected] gzip -d -c /opt/backup/mdb-snap01.gz | dd of=/dev/vg0/mdb-new
mount /dev/vg0/mdb-new /srv/mongodb
如果实例没有启用journal或者journal在独立的卷里面,备份会相对的复杂,你必须刷新所有的写入,并且锁定数据库在备份时禁止写入。
1.刷新数据库并且锁定,使用db.fsyncLock()
2.创建备份
3.然后解锁,使用db.fsyncUnlock()
当开着profile的时候不能db.fsyncLock(),需要先关闭db.setProfilingLevel()
1.获取备份文件
2.启动mongod,使用这些备份文件启动
3.把单个实例转为复制集的一个节点,使用--replSet
4.连接到mongod
5.执行rs.initiate()进行初始化
1. 手动复制数据库文件目录到所有的实例
2. 使用初始化同步数据,同步到成员
复制数据库文件并重启实例:
1. 关闭实例使用shell 命令db.shutdownServer()
2. 复制primary的数据文件到其他成员的dbpatch下
3. 重启mongodb实例
4. 用mongo shell连接到primary,使用rs.add()添加secondary
使用初始化同步更新secondary:
1. 确保预期的成员遍历数据文档都是空的
2. 添加预期的成员到复制集,然后使用初始化同步,复制primary到其他的复制成员
概述:
小集群数据量比较小,如果备份执行时间可以接受,并且数据集有独立的存储就可以考虑,使用dump直接备份。
过程:
抓取数据:如果mongodump没有指定数据库或者collection,mongodump会抓取collection数据和config server的集群数据。不能使用—oplog,这个参数只作用于复制集。可以用--host连接到mongos,进行备份。
恢复数据:和所有的dump备份一样,备份为每个数据库创建了独立的文件夹,每个collection包含一个独立的BSON文件。
概述:
这个过程使用系统快照来抓取Mongdb实例的副本,进行备份。
过程:
这个过程是先停止均衡器,然后备份config数据库,然后再备份每个shard,在备份shard的时候,在创建快照的时候先要停止写入。
可以通过备份secondary成员来达到近似的时间点快照,并且最小化影响集群。
1. 关闭均衡器使用,sh.stopBalancer()来停止
2. 锁定shard复制集中一个成员,这样备份就能够反应某个时间点数据库的状态。为了锁定shard 集群需要做一下2步
a) 使用db.fsyncLock()锁定secondary成员
b) 关闭一个config服务,在备份期间阻止所有元数据的变化。
3. 使用mongodump备份config数据库,使用 mongodump –db_config 备份
4. 使用快照备份,备份复制集成员。
5. 使用db.fsyncUnlock()解锁所有的成员
6. 启用均衡器,use config sh.setBalancerState(true)
概述:
介绍一个使用mongodump创建一个实例的dump过程。
过程:
1. 停止均衡器, sh.stopBalancer()
2. 锁定shard复制集中一个成员,这样备份就能够反应某个时间点数据库的状态,锁定步骤:
a) 关闭复制集的一个成员,确保oplog有足够的空间,支撑到备份结束
b) 关闭一个config数据库,阻止所有的元数据修改
3. 使用mongodump备份config数据库。
4. 使用mongodump在关闭实例的服务器上备份并指定dbpath
5. 启动所有停止的成员
6. 启动均衡器
概述:
Shard集群中,均衡器的用处是在集群中分发数据,在备份时,停止均衡器这样数据块就不会在shard之间移动影响备份,可以手动停止均衡器,也可以用均衡器调度窗口。
过程:
若有例行的备份,囊而就可以用以下方法,开一个调度窗口自动停止均衡器。
useconfig
db.settings.update({_id:"balancer"},{$set:{activeWindow:{start:"6:00",stop:"23:00"}}},true)
但是例行的备份必须在这个时间范围内结束
概述:
从备份中还原一个shard需要一些其他的考虑和实践
过程:
当你还原备份的时候,要记住得,均衡器可能从这个shard移动chunk,所以你必须要手动移动这些chunk。
1. 和还原其他实例一样,先还原这个shard
2. 对于要从这个shard移出的chunk就不用处理,mongos会自动过滤掉这些数据
3. 对于要迁移到这个shard的数据,你必须要手动通过备份其他shard或者其他资源恢复这些数据,可以通过config数据库查看chunk是否被移动。
概述:
首先要有备份,备份可以从文件系统快照备份获得,也可以通过数据库dump获得
过程:
1. 停掉mongos和mongod
2. 如果主机名被修改,你必须手动更新config数据库中的shards,使用新的主机名:
a) 使用一下命令启动config 服务
mongod --configsvr --dbpath /data/configdb --port 27019
b) 恢复config数据库
c) 启动和一个mongos实例
d) 更新config数据库中shards指向新的主机名
3. 还原一下信息:
a) 每个shard的数据库文件
b) 每个config的数据库文件
4. 重启mongos
5. 重启mongod
6. 连接到mongos实例,使用db.printShardingStatus()方法确保集群式可用的。
db.printShardingStatus()
show collections
mongodb没有干净的关闭会导致数据文件不一致,导致数据异常,当然可以干净关闭,或者使用持久性日志,默认mongodb会在每100ms写入数据库journal,这样mongodb在不干净关闭,断电的情况下很快的恢复一致性。
如果你没有复制集和journal你可以使用一下过程恢复数据,当你有复制集的时候,可以从备份中恢复,也可以使用初始化同步恢复。
说明:
当你运行在没有复制集,没有journall的mongod的实例上,要意识到,当你数据库非正常关闭的时候,总是要使用数据库修复选项,如果有复制则可以直接还原备份或者初始化同步。
如果数据文件夹下有个mongod.lock,mongod会拒绝启动,在启动是,进程日志会出现以下信息:
Unclean shutdown detected
这就表示,你需要使用--repair选项来恢复,当你运行是带了选项并且有mongodb.lock文件,进程日志有一下信息:
old lock file: /data/db/mongod.lock. probably means unclean shutdown
出现这个信息,就应该删除这个文件,并且在正常启动前修复数据库
注意:
如果是有复制集就不要使用这个方法,可以使用备份或者使用初始化同步
这里有2中方法修复数据库文件:
1. 用--repair选项并使用--repairpath选线,这样mongod会读取已存在的数据文件,并写入到新的文件中,不修改老文件。使用这个过程可以不删除lock文件
2. 只用--repair,读取存在的文件,写入到新的文件中,并且覆盖老文件,在这个过程前要删除lock文件。
过程:
方法1:
1. 启动mongod带选项--repair,当完成时新的文件会出现在/data/db
mongod --dbpath /data/db --repair --repairpath /data/db0
2. 启动mongod,dbpath指向 /data/db0
这个方法会保留原文件
方法2:
1. 删除lock文件
rm /data/db/mongod.lock
2. 带--repair启动mongod实例
mongod --dbpath /data/db --repair
3. 然后启动mongod实例
mongod --dbpath /data/db
有lock文件就不能启动mongod,如果在很特殊的情况先可以直接删除然后启动恢复数据,这样的话数据库的状态就很难预测
主要介绍:服务端javascript脚本,mongo shell的数据类型,为mongo shell 编写脚本,mongo shell入门,mongo shell帮助信息。mongo shell 快速参考手册
Mongodb支持在服务端运行javascript以下方式运行:
1. mapReduce和db.collection.mapReduce()
2. 使用eval命令或者使用db.eval()
3. $where运算符
4. 直接运行.js文件
可以通过选项--noscripting选项或者noscripting配置文件设置,不执行脚本
可以直接通过mongo shell 执行js文件。
查看concurrency table p594
MongoDB的BSON提供了比JSON多的数据类型
日期类型:BSON提供了多个返回时间类型的方法:
1.Date()直接返回一个表示时间的字符串 如:
var myDateString = Date();
2.Date()可以是用new来构建一个时间类型
var myDateObject = new Date();
3.ISODate()构建一个ISO时间
var myDateObject2 = ISODate();
ObjectId:对于ObjectId Mongo shell提供了一个ObjectId()的封装类来生成ObjectId,如:
new ObjectId
NumberLong:默认mongo shell中的所有数值全是浮点型,mongo使用了NumberLong()生成一个8字节整型。
NumberInt:提供了NumberInt()生成4字节整型
mongo shell中提供了检查类型的方法:
1.instanceof,然会测试的值是否是某个类型的,返回true,false
2.typeof,直接返回一个值的类型
在mongo shell 或者js文件中,可以使用Mongo()连接到实例 如:
new Mongo()
new Mongo(<host>)
new Mongo(<host:port>)
另外也可以使用connect()方法,如:
db = connect("localhost:27020/myDatabase");
考虑一下几点:
1.设置db全局变量,假设当前数据库并不是你要使用的数据库
2.使用db.getLastError()显示的等待写入操作
3.不能够使用 shell help(如use db,show dbs等)具体可以查看p 211中的表格
4.在交互模式下,游标会自动输出内容,在脚本下要使用print(),如:
cursor = db.collection.find();
while ( cursor.hasNext() ) {
printjson( cursor.next() );}
对于prompt也可以使用,javascript脚本建立。
--eval选项:mongo --eval <script>即可
执行js文件:mongo localhost:27017/test myjsfile.js,直接在实例上运行js文件。替代方法,也可以先连接到实例,然后使用load()方法执行。
启动shell:
1.进入mongodb安装目录
2.键入 ./bin/mongo
3.使用db查看当前数据库,使用use 切换数据库
执行查询:使用db.collection.find()查询,db指示了当前的数据库,collection是所查的
find的结果如果赋值给变量,就会直接输出,可以在后面加.pretty()
有一下输出函数:
1.print()不带格式直接输出
2.print(tojson<obj>),和printJson效果一样
3.printJson()带json格式输出
可以直接使用load()执行一个js文件,如:
load("/data/db/scripts/myjstest.js")
可以通过脚本修改Prompt,如:
host = db.serverStatus().host;
prompt = function() {
return db+"@"+host+"$ ";}
设定环境变量,EDITOR然后再启动mongo,在shell中使用edit 就可以在其他编辑器上编辑。如:
export EDITOR=vim
mongo
MongoDB shell version: 2.2.0
> function f() {}
> edit f
> f
function f() {
print("this really works");
}
> f()
this really works
mongo --help
输入help
1.通过show dbs查看数据库
2.db.help查看db下可用的方法
3.查看方法的实现,比如 db.addUser(),输入db.addUser不加括号就可以看方法的实现
1.使用show collections 查看已经存在的collection
2.使用db.collection.help 查看collection的帮助
3.不用括号可以查看方法实现
1.db.collection.find().help()查看游标的帮助信息
2.不加括号可以看方法的实现
使用help misc查看 mongo shell中疯长的可用类。
可以通过方向键获取上一条,下一条命令,这些命令被存放在~/.dbshell文件中。
mongo也有很多命令行选项:
--help:查看所有命令行选项
--nodb:启动mongo shell 但是不连接到数据库
--shell:关联一个文件,运行完文件之后,shell继续运行
help显示帮助
db.help 显示数据库方法
db.collection.help 显示collection方法
show dbs 显示已有数据库
use db 切换数据库上下文
show collections 显示当前数据库下已有collection
show users 显示当前数据库先所有的用户
show profile 显示花费了1ms以上的前5个操作
show database 显示所有可用shujk
load() 执行js文件
包含以下内容,ulimit设置,system collection,Mongodb扩展JSON,数据库profile输出,journaling机制,退出代码和状态。
很多类似unix系统都提供了资源控制,当然有时候默认值太低会导致大量的mongodb常用操作。
通常,所有的mongod和mongos实例会跟踪一下信息:
1.使用1个文件描述符和1个线程跟踪每个income 连接。
2.跟踪每个内部的线程或者pthread都作为一个系统进程
1.mongod实例中每个文件1个文件描述符
2.当journal为true,每个journal文件1个描述符
3.在复制集中,每个mongod维护了到其他所有成员的连接
mongod使用后台线程,用于TTL collection,复制,复制集的健康检查,这些都会消耗一些性能。
客户端连接所使用的线程和文件描述符,所有config数据库和shard的连接,复制集所有成员的连接。考虑一下几点:
1.mongos维护一个连接池,可以直接重用连接不需要重新创建
2.使用maxConns选项限制income连接数
硬ulimit:类似有多少cpu可以让一个用户使用
软ulimit:强制对一个session或者进程的可用资源的限制
所以软ulimit可能会导致无法创建连接的情况,所以ulimit配置很重要。
ulimit是针对每个用户的不同的资源,然后可以通过ulimit -n <value>这种方式修改
可以通过以下shell脚本查看进程限制的状况:
return-limits(){
for process in $@; do
process_pids=`ps -C $process -o pid --no-headers | cut -d " " -f 2`
if [ -z $@ ]; then
echo "[no $process running]"
else
for pid in $process_pids; do
echo "[$process #$pid -- limits]"
cat /proc/$pid/limits
done
fi
done
}
如:return-limits mongod mongos
-f (file size): unlimited
-t (cpu time): unlimited
-v (virtual memory): unlimited 58
-n (open files): 64000
-m (memory size): unlimited 1
-u (processes/threads): 32000
mongodb把一些系统信息都存放在<database>.system.*namespace下面,不要创建以system开头的collection
系统collection包含如下:
<database>.system.namespaces:包含了数据库collection的所有信息
<database>.system.indexs:包含了数据库中所有的索引
<database>.system.profile:包含了数据库profiling信息
<database>.system.users:包含了用户证书信息
<database>.system.js:包含了所有服务端javascript代码
mongodb 手册 2.4.8 page 227自己查看
profile开启后,mongodb会把数据写入到system.profile这个capped collection中,可以直接查询这个capped collection查看捕获的数据。
{
"ts" : ISODate("2012-12-10T19:31:28.977Z"),
"op" : "update",
"ns" : "social.users",
"query" : {
"name" : "jane"
},
"updateobj" : {
"$set" : {
"likes" : [
"basketball",
"trekking"
]
}
},
"nscanned" : 8,
"moved" : true,
"nmoved" : 1,
"nupdated" : 1,
"keyUpdates" : 0,
"numYield" : 0,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(0),
"w" : NumberLong(258)
},
"timeAcquiringMicros" : {
"r" : NumberLong(0),
"w" : NumberLong(7)
}
},
"millis" : 0,
"client" : "127.0.0.1",
"user" : ""
}
具体每个域表示什么意思查 Mongodb手册 v2.4.8 page 261
当启动journal,mongodb会在把写入操作应用到数据文件之前先写入journal文件,写入的间隔为commitIntervalMs,所以当出现故障可能会丢失commitIntervalMs时间的数据。
journal启动后就会创建journal文件,在dbpath下,journal文件被保存在journal文件夹下,文件都是以顺序写的方式写入,干净关闭实例,会把journal文件夹下的文件全部删除。
journal文件是只能追加的,并且都是以j._开头,当journal文件超过1gb的数据,就会自动创建新的文件,一旦文件中的操作都被mongodb应用,那么文件就会被删除,所以一般只会保留2-3个文件。
可以启用smallfiles配置选项,把journal 文件最大设置为128MB。
为了保证写入的速度,可以把文件放到其他系统上。注意如果journal和数据文件不再同一个文件系统中,不要直接使用快照来抓取备份,请查看快照备份。
可能会在mongodb启动的时候经历,预分配延迟,导致这一段时间内,无法连接到数据库。由mongodb决定是通过预分配的方式还是需要的是后再创建文件的方式处理。
journal使用了3部分存储视图:shared view,private view,private cache。
shared view:shared view 保存了更新到数据库文件的数据,是唯一一个可以访问数据库文件的view,当启用journal,mongod要求操作系统映射磁盘上的文件到shared view上,但是不加载他们,然后mongodb把数据库文件按需加载到shared view 上。
private view:保存用户读操作的数据,当新的写入操作时,mongodb把private view 映射到shared view。
private cache:journal是磁盘上的视图,在写入到数据文件之前,把写入操作先写入到了private cache上,用于写入到journal文件上。
journal批量复制写入操作到journal成为组提交。
当写入操作发生,mongodb写入数据到private view,然后批量复制写入操作到journal上,每个块都说明了那些字节在数据库文件中被修改。
然后mongodb把应用journal的写入操作到shared view,这时shared view和数据库文件变得不一致。然后默认60s后,mongodb要求系统刷新shared view 到磁盘上,数据库文件更新。
当mongodb刷新写入操作到磁盘时,mongodb从后面的指针删除这些写入操作。后面的指针和当前活动指针(要刷新到磁盘)差很远。
然后mongodb要求操作系统吧shared view 重新映射到 private view 保持一致性。
扩展阅读:
journal工作原理:http://f.dataguru.cn/thread-139560-1-1.html
当mongodb退出的时候会更一下代码和状态,可以用于troubleshooting。
0:mongodb正常退出
2:和其他选项不兼容导致的错误
3:当命令行指定的主机名和local.sources不符时返回,当oplog collection不可读是也可能会返回。
4:数据库版本和mongod的版本不同。重启mongod加上--upgrade选项更新数据库到mongod支持的版本即可。
5:moveChunk错误是发生
12:在windows下,当mongod接收到ctrl-c,关闭,break或者关闭命令时返回
14:当mongodb发生不可恢复的错误,无法处理的异常或者无法捕捉的signal。会干净的关闭。
20:在windows下,的WSAStartup函数中出错时返回,也可能是,windows下,不能成功安装,启动,删除服务是出现。
45:当mongodb不能打开文件或者不能获取文件上的锁时,出现
47:当mongodb退出,需要大量的时间
48:如果socket关闭,mongod干净退出
49:mongod,mongos收到SCM的关闭信息
100:mongod抛出一个无法捕获的异常