记一次Mongodb中admin数据库导致的事故

前言

MongoDB副本集默认会创建local、admin数据库,local数据库主要存储副本集的元数据,admin数据库则主要存储MongoDB的用户、角色等信息。

Mongodb的gridfs一次插入数据的时候会自动创建几个索引,我们程序里面的账号没有createIndex权限,我需要手动创建一下。结果连接到mongo服务器之后忘记执行use xxxdb来切换数据库了,于是在admin数据库里面创建了一个索引,结果导出一边的程序报出来很多验证问题。

Mongo的admin数据库太脆弱了,只是创建一个索引就挂了。长个教训,以后千万不要手动修改它,更不要用admin保存数据。

反思一下,这次操作失误其实爆出我平时一些不好的习惯。

首先,连接mongo应该指定目标数据。而我之前都是连接到admin,然后用use切换到目标数据库。这样难免会忘记。

$ # 错误使用
$ mongo ourdomain.com/admin -u tom -p tompass
$ # 正确的使用
$ mongo ourdomain.com/mydb -u tom -p tompass --authenticationDatabase admin

第二,错误的在admin数据库执行createIndex,返回的结果明确显示索引创建成功。

{
  "createdCollectionAutomatically" : true,
  "numIndexesBefore" : 1,
  "numIndexesAfter" : 2,
  "ok" : 1,
  ...
}

但是我忽略了,继续在正确的数据库创建索引。不然可以早一些发现问题。

最后,创建索引应该自动化,比如gridfs这种对md5, filename创建索引的。

慎用admin数据库

当Mongod启用auth选项时,用户需要创建数据库帐号,访问时根据帐号信息来鉴权,而数据库帐号信息就存储在admin数据库下。

mongo-9551:PRIMARY> use admin
switched to db admin
mongo-9551:PRIMARY> db.getCollectionNames()
[ "system.users", "system.version" ]
  • system.version存储authSchema的版本信息
  • system.users存储了数据库帐号信息
  • 如果用户创建了自定义的角色,还会有system.roles集合

用户可以在admin数据库下建立任意集合,存储任何数据,但强烈建议不要使用admin数据库存储应用业务数据,最好创建新的数据库。

admin数据库里的system.users、system.roles2个集合的数据,MongoDB会cache在内存里,这样不用每次鉴权都从磁盘加载用户角色信息。目前cache的维护代码,只有在保证system.users、system.roles的写入都串行化的情况下才能正确工作,详情参考官方issue SERVER-16092

从代码中我们可以看出,MongoDB将将admin数据库上的意向写锁(MODE_IX)直接升级为写锁(MODE_X),也就是说admin数据库的写入操作的锁级别只能到DB级别,不支持多个collection并发写入,在写入时也不支持并发读取。如果用户在admin数据库里存储业务数据,则可能遭遇性能问题。

if (supportsDocLocking() || enableCollectionLocking) {
if (supportsDocLocking() || enableCollectionLocking) {
+
+ // The check for the admin db is to ensure direct writes to auth collections
+ // are serialized (see SERVER-16092).
+ if (_id == resourceIdAdminDB && !isRead) {
+ _mode = MODE_X;
+ }
+
_lockState->lock(_id, _mode); 

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 记一次Mongodb中admin数据库导致的事故

    前言 MongoDB副本集默认会创建local.admin数据库,local数据库主要存储副本集的元数据,admin数据库则主要存储MongoDB的用户.角色等信息. Mongodb的gridfs一次插入数据的时候会自动创建几个索引,我们程序里面的账号没有createIndex权限,我需要手动创建一下.结果连接到mongo服务器之后忘记执行use xxxdb来切换数据库了,于是在admin数据库里面创建了一个索引,结果导出一边的程序报出来很多验证问题. Mongo的admin数据库太脆弱了,只是

  • MongoDB在系统数据库local中无法创建用户的解决办法

    前言 我们知道,MongoDB的Oplog (operations log)记录了用户的最近一段时间的操作(时间长短主要受设置的oplogSize和程序的写入更新量的影响).那么,如果其他部门(例如BI团队)需要抽取数据,从 local.oplog.rs中读取解析一个不错的选择. oplog位于local数据下面,为了将权限最小化,大家需要创建此库的权限(还可以将权限细化到集合,再次不讨论). 习惯性的,在local数据库下面创建,但是报错了. 执行脚本 db.createUser( { use

  • SQLServer数据库中开启CDC导致事务日志空间被占满的原因

    SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为: 在执行增删改语句(产生事务日志)的过程中提示,The transaction log for database '***' is full due to 'REPLICATION'(数据库"***"的事务日志已满,原因为"REPLICATION"). CDC以及复制的基本原理粗略地讲,对于日志的使用步骤如下: 1,每当基础表(开启了CDC或者replication的表)产生事务性操作

  • MongoDB中的一些坑(最好不要用)

    MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒.但是薄荷在深入使用 MongoDB 过程中,遇到了不少问题,下面总结几个我们遇到的坑.特别申明:我们目前用的 MongoDB 版本是 2.4.10,曾经升级到 MongoDB 2.6.0 版本,问题依然存在,又回退到 2.4.10 版本. MongoDB 数据库级锁 坑爹指数:5星(最高5星) MongoD

  • MongoDB中连接字符串的编写

    MongoDB数据库与传统的关系型数据库相比,它具有操作简单.完全免费.源码公开等特点,这使MongoDB产品广泛应用于各种大型门户网站和专业网站.由于MongoDB连接并不支持HTTP协议,所有你不能直接通过浏览器访问MongoDB,下面详细介绍MongoDB中连接字符串的编写 一.MongoDB连接字符串常用格式 复制代码 代码如下: mongodb://[username:password@]host1[:port1][,host2[:port2],-[,hostN[:portN]]][/

  • 使用aggregate在MongoDB中查询重复数据记录的方法

    MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*). aggregate() 方法 MongoDB中聚合的方法使用aggregate(). 语法 aggregate() 方法的基本语法格式如下所示: >db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION) 我们知道,MongoDB属于文档型数据库,其存储的文档类型都是JSON对象.正是由于这一特性,我们

  • MongoDB中MapReduce的使用方法详解

    前言 玩过Hadoop的小伙伴对MapReduce应该不陌生,MapReduce的强大且灵活,它可以将一个大问题拆分为多个小问题,将各个小问题发送到不同的机器上去处理,所有的机器都完成计算后,再将计算结果合并为一个完整的解决方案,这就是所谓的分布式计算.本文我们就来看看MongoDB中MapReduce的使用. 打算用mongodb mapreduce之前一定要知道的事!!! mapreduce其实是分批处理数据的,每一百次重新reduce处理,所以到reduce里的数据如果是101条,那就会分

  • 详解MongoDB中的日志模块

    今天简单研究了一下MongoDB里面的日志模块,写篇文章记录下. 01 MongoDB日志组件种类及日志等级 每种数据库都有自己的日志模块,MongoDB也不例外,通常情况下,一个数据库的日志中,记录的是数据库的连接信息.存储信息.网络信息.索引信息以及查询信息等.从MongoDB3.0版本开始,MongoDB在日志中引入了日志等级和日志组件的概念,作为DBA来讲,关注的最多的应该是慢查询日志和连接日志. 在MongoDB中,我们可以通过下面的命令,来获取所有的日志组件种类和对应的日志等级: d

  • MongoDB中优雅删除大量数据的三种方式

    目录 为什么要"瘦身"呢? MongoDB中删除数据的三种方式 三种方式的执行效率对比 1. remove 2. deleteMany 3. bulkWrite 通过 Write Concern 规避主从延迟 删除过程中遇到的Bug 总结 删除大量数据,无论是在哪种数据库中,都是一个普遍性的需求.除了正常的业务需求,我们需要通过这种方式来为数据库"瘦身". 为什么要"瘦身"呢? 1.表的数据量到达一定量级后,数据量越大,表的查询性能会越差. 毕竟

  • Mongodb中MapReduce实现数据聚合方法详解

    Mongodb是针对大数据量环境下诞生的用于保存大数据量的非关系型数据库,针对大量的数据,如何进行统计操作至关重要,那么如何从Mongodb中统计一些数据呢? 在Mongodb中,给我们提供了三种用于数据聚合的方式: (1)简单的用户聚合函数: (2)使用aggregate进行统计: (3)使用mapReduce进行统计: 今天我们首先来讲讲mapReduce是如何统计,在后续的文章中,将另起文章进行相关说明. MapReduce是啥呢?以我的理解,其实就是对集合中的各个满足条件的文档进行预处理

随机推荐