WhattypeoflockingdoesMongoDBuse?
mongodb用的是什么类型的锁
MongoDBusesareaders-writer[1]lockthatallowsconcurrentreadsaccesstoadatabasebutgivesexclusiveaccesstoasinglewriteoperation.
mongodb使用读写锁(共享-排他锁、多读单写锁),允许对数据库进行并发的读访问,并且对每一个写操作提供排他的访问。
Whenareadlockexists,manyreadoperationsmayusethislock.However,whenawritelockexists,asinglewriteoperationholdsthelockexclusively,andnootherreadorwriteoperationsmaysharethelock.
当存在一个读锁时,很多读操作均可使用这个锁。当一个写锁出现,一个写操作排他的占有该锁,并且不被其他的读或者写操作共享。
Locksare“writergreedy,”whichmeanswriteshavepreferenceoverreads.Whenbothareadandwritearewaitingforalock,MongoDBgrantsthelocktothewrite.
锁是偏向于写操作的,即相对于读操作,写操作有更高的优先权。当一个读和写操作同时在等待一个锁时,mongodb优先给写操作分配锁。
HowgranulararelocksinMongoDB?
Changedinversion2.2.
mongodb中锁的粒度
Beginningwithversion2.2,MongoDBimplementslocksonaper-databasebasisformostreadandwriteoperations.Someglobaloperations,typicallyshortlivedoperationsinvolvingmultipledatabases,stillrequireaglobal“instance”widelock.Before2.2,thereisonlyone“global”lockpermongodinstance.
从2.2版本起,对大多数读写操作,mongodb实现了基于数据库的锁。全局操作,典型的比如涉及多个数据库的shortlived操作,依旧会请求实例级别的全局锁,在2.2之前,每个mongodb实例只有一个全局锁。
Forexample,ifyouhavesixdatabasesandonetakesawritelock,theotherfivearestillavailableforreadandwrite.
例如,如果你有六个数据库,其中一个有写锁,其他的五个仍然可以进行读写。
HowdoIseethestatusoflocksonmymongodinstances?
我如何查看mongod实例的锁状态
Forreportingonlockutilizationinformationonlocks,useanyofthefollowingmethods:
db.serverStatus(),
db.currentOp(),
mongotop,
mongostat,and/or
theMongoDBMonitoringService(MMS)
Specifically,thelocksdocumentintheoutputofserverStatus,orthelocksfieldinthecurrentoperationreportingprovidesinsightintothetypeoflocksandamountoflockcontentioninyourmongodinstance.
Toterminateanoperation,usedb.killOp().
Doesareadorwriteoperationeveryieldthelock?
Newinversion2.0.
读写操作会交出锁吗?
Areadandwriteoperationswillyieldtheirlocksifthemongodreceivesapagefaultorfetchesdatathatisunlikelytobeinmemory.Yieldingallowsotheroperationsthatonlyneedtoaccessdocumentsthatarealreadyinmemorytocompletewhilemongodloadsdocumentsintomemory.
如果mongod接收到未命中的缓存页或者去取不在内存中的数据,读写操作将放弃他们的锁。这样就允许mongod进行其他只需要访问内存里的文档即可完成的操作,同时加载自身需要的数据到内存。
Additionally,writeoperationsthataffectmultipledocuments(i.e.update()withthemultiparameter,)willyieldperiodicallytoallowreadoperationsduringtheselogwriteoperations.Similarly,longrunningreadlockswillyieldperiodicallytoensurethatwriteoperationshavetheopportunitytocomplete.
此外,多个文档上的写操作(比如带有multi操作的update),在日志写的时间内,会周期性地交出锁以容许读操作。类似的,长时间的读锁也会定期的退让以便写操作有机会完成。
Changedinversion2.2:TheuseofyieldingexpandedgreatlyinMongoDB2.2.Includingthe“yieldforpagefault.”MongoDBtracksthecontentsofmemoryandpredictswhetherdataisavailablebeforeperformingaread.IfMongoDBpredictsthatthedataisnotinmemoryareadoperationyieldsitslockwhileMongoDBloadsthedatatomemory.Oncedataisavailableinmemory,thereadwillreacquirethelocktocompletestheoperation.
2.2版本极大地扩展了yielding,包括因为pagefault的yielding。mongodb会跟踪内存并在执行一个读之前预判数据是否可用。如果数据不在内存,读操作即交出锁同时mongodb加载数据到内存。一旦数据到了内存,该读操作会再次搜索那个读锁完成此次操作。
##################################################
--1 MongoDB 使用的锁
MongoDB 使用的是“readers-writer”锁,可以支持并发但有很大的局限性,当一个读锁存在,许多
读操作可以使用这把锁,然而, 当一个写锁的存在,一个单一的写操作会 exclusively 持有该锁,同时
其它读,写操作不能使用共享这个锁;举个例子,假设一个集合里有 10 个文档,多个 update 操作不能
并发在这个集合上,即使是更新不同的文档。
--2 锁的粒度
在 2.2 版本以前,mongod 只有全局锁;在 2.2 版本开始,大部分读写操作只锁一个库,相对之前版本,
这个粒度已经下降,例如如果一个 mongod 实例上有 5 个库,如果只对一个库中的一个集合执行写操作,那
么在写操作过程中,这个库被锁;而其它 5 个库不影响。相比 RDBMS 来说,这个粒度已经算很大了!
--3 如何查看锁的状态
db.serverStatus()
db.currentOp()
mongotop
mongostat
the MongoDB Monitoring Service (MMS)
--4 哪些操作会对数据库产生锁?
下表列出了常见数据库操作产生的锁。
Issue a query | Read lock |
Get more data from acursor | Read lock |
Insert data | Write lock |
Remove data | Write lock |
Update data | Write lock |
Map-reduce | Read lock and write lock, unless operations are specified as non-atomic. Portions of map-reduce jobs can run concurrently. |
Create an index | Building an index in the foreground, which is the default, locks the database for extended periods of time. |
db.eval() | Write lock.db.eval()blocks all other JavaScript processes. |
eval | Write lock. If used with thenolocklock option, theevaloption does not take a write lock and cannot write data to the database. |
aggregate() | Read lock |
--5 哪些数据库管理操作会锁数据库?
某些数据库管理操作会 exclusively 锁住数据库,以下命令需要申请 exclusively 锁,并锁定一段时间
db.collection.ensureIndex(),
reIndex,
compact,
db.repairDatabase(),
db.createCollection(), when creating a very large (i.e. many gigabytes) capped collection,
db.collection.validate(),
db.copyDatabase().This operation may lock all databases
以下命令需要申请 exclusively 锁,但锁定很短时间。
db.collection.dropIndex(),
db.collection.getLastError(),
db.isMaster(),
rs.status() (i.e. replSetGetStatus,)
db.serverStatus(),
db.auth(), and
db.addUser().
备注:可见,一些查看命令也会锁库,在比较繁忙的生产库中,也会有影响的。
--6 锁住多个库的操作
以下数据库操作会锁定多个库。
db.copyDatabase() must lock the entire mongod instance at once.
Journeying, which is an internal operation, locks all databases for short intervals.
All databases share a single journal.
User authentication locks the admin database as well as the database the user is accessing.
All writes to a replica set’s primary lock both the database receiving the writes and the
local database. The lock for the local database allows the mongod to write to the primary’s oplog.