MongoDB之insert"安全操作"
MongoDB之insert"安全操作"
MongoDB中插入、删除、更新操作都是瞬间完成的,它们都不需要等待数据库响应。默认采用的不是“安全”模式的。
01 #-*- coding:UTF-8 -*- 02 ''' 03 Created on 2013-9-20 04 05 @author: tyk 06 ''' 07 from pymongo import Connection 08 import time 09 10 def save1(): 11 conn = Connection('localhost', 27017) #获取一个连接 12 conn.drop_database('test1') 13 db = conn.test1 14 t = db.T 15 for i in range(1, 100000): 16 #t.insert({'num': i }, w = 1) 17 t.insert({'num': i }) 18 19 def save2(): 20 with open('LICENSE') as f: 21 data = f.read()#读取文本,将其更新到文档中 22 conn = Connection('localhost', 27017) #获取一个连接 23 db = conn.test1 24 t = db.T 25 print t.count() 26 #db.collection.find().snapshot() 27 for n in t.find(timeout=False):#查询出来所有的文档,遍历 28 t.update({'_id': n['_id']}, {'$set':{'data':data}}) 29 print n['num'] 30 31 if __name__ == '__main__': 32 save1() 33 #time.sleep(10) 34 save2()
实验一 :(第二天在此模拟时始终无法出现以下结果!)
save1()首先插入
1
t.insert({'num': i })
紧接着save2()进行查询
1 for n in t.find(timeout=False):#查询出来所有的文档,遍历 2 t.update({'_id': n['_id']}, {'$set':{'data':data}})
打印结果:
第一次:
1 1 2 {u'_id': ObjectId('5255593d06d80e0c601502af'), u'num': 1} 3 {u'_id': ObjectId('5255593d06d80e0c601502b0'), u'num': 2}
第二次:
1 2 2 {u'_id': ObjectId('5255593d06d80e0c601502af'), u'num': 1} 3 {u'_id': ObjectId('5255593d06d80e0c601502b0'), u'num': 2}
实验二:
save1()和save2()之间sleep(10)
打印结果:
1 999999 2 {u'_id': ObjectId('5255593d06d80e0c601502af'), u'num': 1} 3 {u'_id': ObjectId('5255593d06d80e0c601502b0'), u'num': 2} 4 ......
实验三:
采用安全模式进行插入(python驱动建议以‘w’取代‘safe’)
1 t.insert({'num': i }, w = 1) 打印结果: 1 999999 2 {u'_id': ObjectId('5255593d06d80e0c601502af'), u'num': 1} 3 {u'_id': ObjectId('5255593d06d80e0c601502b0'), u'num': 2} 4
......
疑问:
本次实验本来是为了解决上次一个问题“一个客户端进行更新时(对文档结构产出较大变化的更新),另一个客户端进行一次find()后更新操作立刻停止,貌似一直发生阻塞。针对这个问题的猜想可能是文档发生大规模移动,使用游标可能就会有一些问题(参考《MongoDB权威指南》 4.5.5 获取一致结果 一章),本来想在进行插入时另一客户端查询时使用快照db.T.find({},{'num':1}).snapshot()查询。但是这次并没有明显出现阻塞问题。
1.实验不严谨,更新对文档产生较大影响要发生移动时MongoDB会有学习功能,会为每个文档预留相应的空间。这次更新文档为同一篇文章,大小一样。也可能只在第一次发生了一次大规模移动,后续的预留空间都够存储文档了。有待进一步验证
2.前一天实验中在后续的查询Insert和find结果是不一致的,必须借助于"安全操作"才可以同步。但是在后来实验中没有使用"安全操作"再也不出现这种情况了?
3.在实验中在另一客户端采用find()和find().snapshot()两次查出来的文档是不一样的。
find()
find({},{'num':1}).snapshot()
使用快照查询返回的是按照插入顺序返回的,而直接使用find()查询返回的都是还没更新的文档(data字段还没更新上),后来根据更新时同步打印的记录显示直接调用find()返回的就是另一客户端将要更新的文档,随着逐步更新,find()返回的值也紧跟着变化。貌似两个客户端使用的是同一个游标。