1. 程式人生 > >淺嘗輒止MongoDB:管理(1)

淺嘗輒止MongoDB:管理(1)

目錄

        MongoDB和SQL資料庫之間的主要區別是:

  • 不需要在伺服器上建立資料庫、集合或欄位,因為MongoDB將在訪問它們時動態建立這些元素。
  • MongoDB中的所有物件和元素名稱都區分大小寫。

一、控制訪問許可權

        MongoDB支援簡單的基於角色的認證系統,其中包含預定義的系統角色和使用者定義的定製角色,通過該系統可以控制使用者對資料庫的訪問及他們被授予的訪問級別。大多數修改配置資料或者對結果進行大幅調整的MongoDB伺服器命令都被限制在專門的admin資料庫中執行,該資料庫將在每個新的MongoDB安裝時自動建立。

        預設情況下,MongoDB不使用任何認證方式。任何可以訪問網路的人都可以連線到伺服器並執行命令。不過,可以在任何資料庫中新增使用者,這樣就可以對MongoDB進行配置,使得在訪問資料庫時要求進行伺服器驗證。

        MongoDB支援對每個資料庫的訪問進行單獨控制,訪問控制資訊被儲存在特有的system.users集合中。對於希望訪問兩個資料庫(例如db1和db2)的普通使用者,他們的憑據和許可權必須被同時新增到兩個資料庫中。

        如果在不同資料庫為同一使用者分別建立了登入和訪問許可權,這些記錄不會互相同步。換句話說,修改一個數據庫中的使用者密碼不會影響另一個數據庫中的使用者密碼。該規則有一個例外:任何新增到admin資料庫中的使用者,在所有資料庫中都擁有相同的訪問許可權,不需要為這樣的使用者單獨賦予許可權。

1. 新增admin使用者

> use admin;
switched to db admin
> db.createUser({user : "admin", pwd : "pass", roles: [ { role : "readWrite", db : "admin"
... }, { role: "userAdminAnyDatabase", db : "admin" } ] });
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "readWrite",
            "db" : "admin"
        },
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}
> db.system.users.findOne({user:"admin"})
{
    "_id" : "admin.admin",
    "user" : "admin",
    "db" : "admin",
    "credentials" : {
        "SCRAM-SHA-1" : {
            "iterationCount" : 10000,
            "salt" : "kLpduUuLPNHh5Z8RjuhPnw==",
            "storedKey" : "PKPFi5NDRmvDZj88cdSz1ZM+Ffk=",
            "serverKey" : "6r0EKeHkjp9pymkLJeLD0+krutY="
        },
        "SCRAM-SHA-256" : {
            "iterationCount" : 15000,
            "salt" : "BkiI7zbBQJ0b4LghbuGE0YxmvlbYNX0HryoN/w==",
            "storedKey" : "sgNs3puWRadYmxXjfSgoEzlxj1oOwB/Y5RdFQ2HTx5c=",
            "serverKey" : "+OLxG/kecq4zoWcOduouoLC1YFhQZ86wS/oMz1EXZ0o="
        }
    },
    "roles" : [
        {
            "role" : "readWrite",
            "db" : "admin"
        },
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}
>

2. 啟用身份認證

        可以用以下兩種方式啟用身份認證:

  • 在配置檔案(如mongodb.conf)中新增auth=true,然後重啟MongoDB。
  • 停止伺服器並在啟動引數中新增--auth。

3. 在mongo控制檯中執行身份驗證

[[email protected]~]$mongo
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.2
> use admin
switched to db admin
> show collections;
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> db.auth("admin","pass");
1
> show collections;
> db.getUsers();
[
    {
        "_id" : "admin.admin",
        "user" : "admin",
        "db" : "admin",
        "roles" : [
            {
                "role" : "readWrite",
                "db" : "admin"
            },
            {
                "role" : "userAdminAnyDatabase",
                "db" : "admin"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }
]
>

        如果使用admin憑證訪問admin之外的資料庫,那麼必須首先針對admin資料庫進行認證,否則無法訪問系統中的任何其它資料庫。

[[email protected]~]$mongo
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.2
> use test
switched to db test
> show collections;
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> db.auth("admin","pass");
Error: Authentication failed.
0
> use admin
switched to db admin
> db.auth("admin","pass");
1
> use test;
switched to db test
> show collections;
products
>

5. 修改使用者憑據

[[email protected]~]$mongo admin
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 4.0.2
> db.auth("admin", "pass");
1
> use test;
switched to db test
> db.createUser({user : "foo", pwd : "foo" , roles: [ { role : "read", db : "test" } ] } );
Successfully added user: {
    "user" : "foo",
    "roles" : [
        {
            "role" : "read",
            "db" : "test"
        }
    ]
}
> db.getUsers();
[
    {
        "_id" : "test.foo",
        "user" : "foo",
        "db" : "test",
        "roles" : [
            {
                "role" : "read",
                "db" : "test"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }
]
> db.updateUser( "foo", {pwd : "pass", roles: [ { role : "dbAdmin", db : "test" } ] });
> db.getUsers();
[
    {
        "_id" : "test.foo",
        "user" : "foo",
        "db" : "test",
        "roles" : [
            {
                "role" : "dbAdmin",
                "db" : "test"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }
]
> db.auth("foo", "foo");
Error: Authentication failed.
0
> db.auth("foo", "pass");
1
>

6. 新增只讀使用者

[[email protected]~]$mongo admin
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 4.0.2
> db.auth("admin", "pass");
1
> use test;
switched to db test
> db.createUser({user : "shadycharacter", pwd : "shadypassword" , roles: [ { role : "read", db : "test" } ] } );
Successfully added user: {
    "user" : "shadycharacter",
    "roles" : [
        {
            "role" : "read",
            "db" : "test"
        }
    ]
}
> db.auth("shadycharacter", "shadypassword");
1
> db.products.findOne();
2018-10-10T16:05:26.084+0800 E QUERY    [js] Error: error: {
    "ok" : 0,
    "errmsg" : "too many users are authenticated",
    "code" : 13,
    "codeName" : "Unauthorized"
} :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/query.js:708:1
[email protected]/mongo/shell/query.js:113:28
[email protected]/mongo/shell/query.js:288:5
[email protected]/mongo/shell/collection.js:254:10
@(shell):1:1
> exit
bye
[[email protected]~]$mongo test
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/test
MongoDB server version: 4.0.2
> db.auth("shadycharacter", "shadypassword");
1
> db.products.findOne();
{ "_id" : 20, "item" : "large box", "qty" : 20 }
> db.products.insertOne(  { _id: 100, item: "large box", qty: 20 }  );
2018-10-10T16:05:59.808+0800 E QUERY    [js] WriteCommandError: not authorized on test to execute command { insert: "products", ordered: true, lsid: { id: UUID("679644a1-2281-406e-85b1-986948ee04b4") }, $db: "test" } :
WriteCommandError({
    "ok" : 0,
    "errmsg" : "not authorized on test to execute command { insert: \"products\", ordered: true, lsid: { id: UUID(\"679644a1-2281-406e-85b1-986948ee04b4\") }, $db: \"test\" }",
    "code" : 13,
    "codeName" : "Unauthorized"
})
[email protected]/mongo/shell/bulk_api.js:420:48
Bulk/[email protected]/mongo/shell/bulk_api.js:902:1
Bulk/[email protected]/mongo/shell/bulk_api.js:1150:21
[email protected]/mongo/shell/crud_api.js:252:9
@(shell):1:1
>

7. 刪除使用者

[[email protected]~]$mongo admin
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 4.0.2
> db.auth("admin","pass");
1
> use test;
switched to db test
> db.dropUser("shadycharacter");
true
> db.getUsers();
[
    {
        "_id" : "test.foo",
        "user" : "foo",
        "db" : "test",
        "roles" : [
            {
                "role" : "dbAdmin",
                "db" : "test"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }
]
>

二、備份與還原

1. mongodump的各種備份方式

# 無賬號、密碼
mongodump -o backup   #備份所有資料庫到backup目錄下,每個資料庫一個檔案,除local資料庫外。
mongodump -d abc -o backup   #備份abc資料庫到backup目錄下。
mongodump -d abc -c ddd -o backup   #備份abc資料庫下的ddd集合。

#有賬號、密碼
mongodump -udba -pdba -d abc -c ddd -o backup   #備份abc資料庫下的ddd集合。
mongodump --host=127.0.0.1 --port=27017 -udba -p --db=abc --collection=ddd -o backup

        這裡需要注意的是:在認證備份中,比如在abc資料庫中,需要其有dba這個賬號才可以執行備份,要是abc資料庫裡沒有賬號,那麼需要在admin上認證,再執行需要加:authenticationDatabase引數指定儲存使用者憑證的資料庫,沒有指定則去-d指定的資料庫認證。最好還是設定專本備份的賬號。

mongodump -udba -pdba -d abc --authenticationDatabase admin -o backup   #在admin資料庫下認證之後再去備份abc資料庫。

2. mongodump示例

        備份test庫:

[[email protected]~]$mongodump -u wxy --authenticationDatabase admin -d test -o ./dump
Enter password:

2018-10-10T10:05:25.831+0800    writing test.products to 
2018-10-10T10:05:25.903+0800    done dumping test.products (3 documents)
[[email protected]~]$

        命令執行後生成./dump/test目錄和相關檔案:

[[email protected]~]$ll ./dump/test
total 8
-rw-rw-r-- 1 mongodb mongodb 154 Oct 10 10:05 products.bson
-rw-rw-r-- 1 mongodb mongodb 127 Oct 10 10:05 products.metadata.json
[[email protected]~]$

        products是集合名稱。.bson檔案儲存集合資料,該檔案只是MongoDB內部儲存的BSON格式檔案的一個副本。.json檔案儲存元資料,包括集合的索引及其定義。mongodump工具在寫入備份檔案之前不會清空輸出目錄中的內容,而只是覆蓋同名檔案。除非希望覆蓋備份中的資料,否則應該在使用mongodump之前保證清空目標目錄。

3. 自動備份指令碼

#!/bin/bash
##########################################
# Edit these to define source and destinations

MONGO_DBS=""
BACKUP_TMP=~/tmp
BACKUP_DEST=~/backups
MONGODUMP_BIN=/home/mongodb/mongodb-4.0.2/bin/mongodump
TAR_BIN=/usr/bin/tar

##########################################

BACKUPFILE_DATE=`date +%Y%m%d-%H%M`

# _do_store_archive <Database> <Dump_dir> <Dest_Dir> <Dest_file>

function _do_store_archive {
         mkdir -p $3
         cd $2
         tar -cvzf $3/$4 dump
}

# _do_backup <Database name>

function _do_backup {
         UNIQ_DIR="$BACKUP_TMP/$1"`date "+%s"`
         mkdir -p $UNIQ_DIR/dump
         echo "dumping Mongo Database $1"
         if [ "all" = "$1" ]; then

                 $MONGODUMP_BIN -o $UNIQ_DIR/dump -u wxy --authenticationDatabase admin
         else

                 $MONGODUMP_BIN -d $1 -o $UNIQ_DIR/dump -u wxy --authenticationDatabase admin

         fi

         KEY="database-$BACKUPFILE_DATE.tgz"
         echo "Archiving Mongo database to $BACKUP_DEST/$1/$KEY"
         DEST_DIR=$BACKUP_DEST/$1
         _do_store_archive $1 $UNIQ_DIR $DEST_DIR $KEY

         rm -rf $UNIQ_DIR
}

# check to see if individual databases have been specified, otherwise backup the whole server to "all"

if [ "" = "$MONGO_DBS" ]; then
        MONGO_DB="all"
        _do_backup $MONGO_DB
else
        for MONGO_DB in $MONGO_DBS; do
                _do_backup $MONGO_DB
        done
fi

4. mongorestore的各種還原方式

mongorestore -udba -pdba -d abc backup/abc   #還原abc資料庫。
mongorestore -udba -pdba -d abc --drop backup/abc   #還原之前先刪除原來資料庫(集合)。
mongorestore -udba -pdba -d abc -c ddd --drop backup/abc/ddd.bson   #還原abc庫中的ddd集合。
mongorestore --host=127.0.0.1 --port=27017 -udba -pdba -d abc -c test --drop backup/abc/test.bson   #還原abc庫中的test集合。
mongorestore --host=127.0.0.1 --port=27017 -udba -pdba -d abc -c ooo --drop backup/abc/test.bson   #還原abc庫中的test集合到ooo集合。

5. mongorestore示例

        恢復整個備份:

[[email protected]~]$mongorestore --drop -u wxy --authenticationDatabase admin ./dump
Enter password:

2018-10-10T10:06:11.239+0800    preparing collections to restore from
2018-10-10T10:06:11.381+0800    reading metadata for test.products from dump/test/products.metadata.json
2018-10-10T10:06:11.465+0800    restoring test.products from dump/test/products.bson
2018-10-10T10:06:11.541+0800    no indexes to restore
2018-10-10T10:06:11.541+0800    finished restoring test.products (3 documents)
2018-10-10T10:06:11.541+0800    done
[[email protected]~]$

        恢復單個庫:

[[email protected]~]$mongorestore --drop -u wxy --authenticationDatabase admin -d test ./dump/test/
Enter password:

2018-10-10T10:16:22.666+0800    the --db and --collection args should only be used when restoring from a BSON file. Other uses are deprecated and will not exist in the future; use --nsInclude instead
2018-10-10T10:16:22.666+0800    building a list of collections to restore from dump/test dir
2018-10-10T10:16:22.739+0800    reading metadata for test.products from dump/test/products.metadata.json
2018-10-10T10:16:22.781+0800    restoring test.products from dump/test/products.bson
2018-10-10T10:16:22.818+0800    no indexes to restore
2018-10-10T10:16:22.818+0800    finished restoring test.products (3 documents)
2018-10-10T10:16:22.818+0800    done
[[email protected]~]$

        恢復單個集合:

[[email protected]~]$mongorestore --drop -u wxy --authenticationDatabase admin -d test -c products ./dump/test/products.bson 
Enter password:

2018-10-10T10:17:33.139+0800    checking for collection data in dump/test/products.bson
2018-10-10T10:17:33.287+0800    reading metadata for test.products from dump/test/products.metadata.json
2018-10-10T10:17:33.372+0800    restoring test.products from dump/test/products.bson
2018-10-10T10:17:33.449+0800    no indexes to restore
2018-10-10T10:17:33.449+0800    finished restoring test.products (3 documents)
2018-10-10T10:17:33.449+0800    done
[[email protected]~]$

三、匯入與匯出

1. mongoimport的各種匯入方式

        mongoimport支援CSV(逗號分隔)、TSV(TAB分隔)、JSON(支援可變模式)三種檔案格式的資料。

mongoimport -udba -pdba -dabc -ciii --authenticationDatabase admin backup/ddd.txt   #匯入到iii集合
mongoimport -udba -pdba -dabc -ceee --type=csv --headerline --authenticationDatabase admin backup/ddd.csv   #csv匯入,需要指定headerline
mongoimport -udba -pdba -dabc -ceee --type=csv --headerline --ignoreBlanks --drop --authenticationDatabase admin backup/ddd.csv   #不匯入空欄位,指定ignoreBlanks。

2. mongoimport示例

[[email protected]~]$more a.txt 
_id,item,qty
20,large box,20
21,small box,55
22,medium box,30
[[email protected]~]$mongoimport --drop -u wxy --authenticationDatabase admin -d test -c products --type csv --headerline a.txt
Enter password:

2018-10-10T12:44:30.216+0800    connected to: localhost
2018-10-10T12:44:30.287+0800    dropping: test.products
2018-10-10T12:44:30.447+0800    imported 3 documents
[[email protected]~]$mongo -u wxy --authenticationDatabase admin test --eval "printjson(db.products.find().count())"
MongoDB shell version v4.0.2
Enter password: 
connecting to: mongodb://127.0.0.1:27017/test
MongoDB server version: 4.0.2
3
[[email protected]~]$

3. mongoexport的各種匯出方式

mongoexport -udba -pdba -dabc -cddd --authenticationDatabase admin -o backup/ddd.txt   # 匯出txt文字
mongoexport -udba -pdba -dabc -cddd -f sno,sname --authenticationDatabase admin -o backup/ddd.txt   # 指定欄位匯出txt文字
mongoexport -udba -pdba -dabc -cddd -f sno,sname --csv --authenticationDatabase admin -o backup/ddd.csv   # 匯出成csv格式的需要指定欄位-f
mongoexport -udba -pdba -dabc -cddd -q '{"sno":{"$gte":5}}' -f sno,sname --csv --authenticationDatabase admin -o backup/ddd.csv   # 按照-q裡的條件匯出

4. mongoexport示例

> db.products.find();
{ "_id" : 20, "item" : "large box", "qty" : 20 }
{ "_id" : 21, "item" : "small box", "qty" : 55 }
{ "_id" : 22, "item" : "medium box", "qty" : 30 }
>

        帶條件匯出products集合:

[[email protected]~]$mongoexport -u wxy --authenticationDatabase admin -d test -c products -q '{qty:{$gte:30}}' -f _id,item,qty --type=csv -o a.csv
Enter password:

2018-10-10T13:52:02.762+0800    connected to: localhost
2018-10-10T13:52:02.762+0800    exported 2 records
[[email protected]~]$more a.csv
_id,item,qty
21,small box,55
22,medium box,30
[[email protected]~]$