mongodb源码分析(十一)数据的删除
来源:互联网 发布:淘宝店官网 编辑:程序博客网 时间:2024/06/15 21:10
本文我们将删除,删除操作概括起来就是遍历将collection中数据对应的索引删除,然后是删除数据,最后将删除
的空间加入到之前文章描述的deletelist中.下面我们来看具体的代码吧.删除的入口是receiveDelete函数.
void receivedDelete(Message& m, CurOp& op) { DbMessage d(m); const char *ns = d.getns(); op.debug().ns = ns; int flags = d.pullInt(); bool justOne = flags & RemoveOption_JustOne;//值删除单条doc bool broadcast = flags & RemoveOption_Broadcast; verify( d.moreJSObjs() ); BSONObj pattern = d.nextJsObj(); op.debug().query = pattern; op.setQuery(pattern); PageFaultRetryableSection s; while ( 1 ) { try { Lock::DBWrite lk(ns); // writelock is used to synchronize stepdowns w/ writes uassert( 10056 , "not master", isMasterNs( ns ) ); // if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit if ( ! broadcast && handlePossibleShardedMessage( m , 0 ) ) return; Client::Context ctx(ns);//具体的删除函数 long long n = deleteObjects(ns, pattern, justOne, true); lastError.getSafe()->recordDelete( n ); break; } catch ( PageFaultException& e ) { LOG(2) << "recordDelete got a PageFaultException" << endl; e.touch(); } } }receiveDelete->deleteObjects
long long deleteObjects(const char *ns, BSONObj pattern, bool justOne, bool logop, bool god, RemoveSaver * rs ) { long long nDeleted = 0;//根据查询条件得到游标 shared_ptr< Cursor > creal = NamespaceDetailsTransient::getCursor( ns, pattern ); if( !creal->ok() ) return nDeleted; shared_ptr< Cursor > cPtr = creal; auto_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout, cPtr, ns) ); cc->setDoingDeletes( true ); CursorId id = cc->cursorid(); bool canYield = !god && !(creal->matcher() && creal->matcher()->docMatcher().atomic()); do { // TODO: we can generalize this I believe // bool willNeedRecord = (creal->matcher() && creal->matcher()->needRecord()) || pattern.isEmpty() || isSimpleIdQuery( pattern ); if ( ! willNeedRecord ) { // TODO: this is a total hack right now // check if the index full encompasses query if ( pattern.nFields() == 1 && str::equals( pattern.firstElement().fieldName() , creal->indexKeyPattern().firstElement().fieldName() ) ) willNeedRecord = true; } if ( canYield && ! cc->yieldSometimes( willNeedRecord ? ClientCursor::WillNeed : ClientCursor::MaybeCovered ) ) { cc.release(); // has already been deleted elsewhere // TODO should we assert or something? break; } if ( !cc->ok() ) { break; // if we yielded, could have hit the end } // this way we can avoid calling prepareToYield() every time (expensive) // as well as some other nuances handled cc->setDoingDeletes( true ); DiskLoc rloc = cc->currLoc(); BSONObj key = cc->currKey(); bool match = creal->currentMatches(); cc->advance(); if ( ! match ) continue; // SERVER-5198 Advance past the document to be modified, but see SERVER-5725. while( cc->ok() && rloc == cc->currLoc() ) {//多值索引就会出现这种状况,需要跳过同一条记录 cc->advance(); } bool foundAllResults = ( justOne || !cc->ok() ); if ( !foundAllResults ) { // NOTE: Saving and restoring a btree cursor's position was historically described // as slow here. cc->c()->prepareToTouchEarlierIterate(); } if ( logop ) {//记录删除动作 BSONElement e; if( BSONObj::make( rloc.rec() ).getObjectID( e ) ) { BSONObjBuilder b; b.append( e ); bool replJustOne = true; logOp( "d", ns, b.done(), 0, &replJustOne ); } else { problem() << "deleted object without id, not logging" << endl; } } if ( rs )//将要删除的doc记录下来 rs->goingToDelete( rloc.obj() /*cc->c->current()*/ ); theDataFileMgr.deleteRecord(ns, rloc.rec(), rloc);//记录的删除 nDeleted++; if ( foundAllResults ) { break; } cc->c()->recoverFromTouchingEarlierIterate(); if( !god ) getDur().commitIfNeeded(); if( debug && god && nDeleted == 100 ) log() << "warning high number of deletes with god=true which could use significant memory" << endl; } while ( cc->ok() ); if ( cc.get() && ClientCursor::find( id , false ) == 0 ) { // TODO: remove this and the id declaration above if this doesn't trigger // if it does, then i'm very confused (ERH 06/2011) error() << "this should be impossible" << endl; printStackTrace(); cc.release(); } return nDeleted; }
receiveDelete->deleteObjects->deleteRecord
void DataFileMgr::deleteRecord(const char *ns, Record *todelete, const DiskLoc& dl, bool cappedOK, bool noWarn, bool doLog ) { NamespaceDetails* d = nsdetails(ns); if ( d->isCapped() && !cappedOK ) { out() << "failing remove on a capped ns " << ns << endl; uassert( 10089 , "can't remove from a capped collection" , 0 ); return; } BSONObj toDelete; if ( doLog ) { BSONElement e = dl.obj()["_id"]; if ( e.type() ) { toDelete = e.wrap(); } } /* check if any cursors point to us. if so, advance them. */ ClientCursor::aboutToDelete(dl); unindexRecord(d, todelete, dl, noWarn);//删除索引,循环删除所有索引中记录todelete的部分. _deleteRecord(d, ns, todelete, dl);//实际的数据删除并将其空间添加到deletedList中 NamespaceDetailsTransient::get( ns ).notifyOfWriteOp(); if ( ! toDelete.isEmpty() ) { logOp( "d" , ns , toDelete ); } }到这里删除过程结束,可见这部分流程是很简单的.
原文链接: mongodb源码分析(十一)数据的删除
作者: yhjj0108,杨浩
- mongodb源码分析(十一)数据的删除
- mongodb源码分析(十)数据的插入
- mongodb源码分析(十二)数据的更新
- Mongodb源码分析--删除记录
- Mongodb源码分析--删除记录
- Mongodb源码分析--删除记录
- Mongodb源码分析--删除记录
- Mongodb源码分析--删除记录
- 【mongodb系统学习之十一】mongodb删除数据
- mongodb源码分析-数据插入
- mongodb源码分析(二十一)mongos 查询与添加
- mongodb源码分析(二十四)mongos数据的平衡
- Mongodb的数据备份与删除
- mongoDB的基本操作之数据删除
- mongoDB(3):数据的更新、插入、删除
- Mongodb 删除重复数据的几个方法
- mongodb源码分析(二)mongod的启动
- mongodb源码分析(三)mongo的启动
- linux 下 启动tomcat时 提示找不到catalina.sh
- 快速傅立叶变换的意义及应用
- CF 254D Rats(枚举+bfs+各种乱搞)
- ubuntu linux64 bashrc文件 环境配置
- 2D-FFT(二维快速傅里叶变换) 源码
- mongodb源码分析(十一)数据的删除
- Windows下WSH/JS实现SVN服务器钩子脚本阻止提交空日志信息和垃圾文件
- 升级android Sdk出现 SDK Manager failed to insatll错误
- 利用矩阵的n次方求图的连通性
- GCC的内嵌汇编语法
- 王牌流量爆刷器 流量提升工具 网站刷新 增加浏览量 王牌软件
- Lua基础 基本介绍
- SQL语法大全
- 二维数组基础