Адміністрування бази даних MongoDB для веб-застосунку

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Адміністрування бази даних MongoDB для веб-застосунку
Складна
постійна підтримка
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Адміністрування баз даних MongoDB для веб-додатків

MongoDB — документна база з горизонтальним масштабуванням. Гнучка схема зручна під час розробки, але у продакшені потребує дисципліни: без індексів запити стають скануванням колекції, без компактифікації WiredTiger не звільняє місце, без моніторингу oplog реплики відстають і втрачають синхронізацію.

Попередній аудит

// mongosh
use mydb

// Статистика бази
db.stats({ scale: 1024 * 1024 }) // у МБ

// Статистика колекцій
db.runCommand({ listCollections: 1 }).cursor.firstBatch.forEach(c => {
    const stats = db[c.name].stats({ scale: 1024 })
    printjson({
        name: c.name,
        docs: stats.count,
        size_kb: stats.size,
        storageSize_kb: stats.storageSize,
        totalIndexSize_kb: stats.totalIndexSize,
        nindexes: stats.nindexes
    })
})

// Індекси колекції з розмірами
db.orders.stats().indexSizes

// Операції, що виконуються прямо зараз (> 1 секунди)
db.currentOp({ "secs_running": { $gt: 1 } })

Індексування

// Складений індекс для типового запиту за користувачем та датою
db.orders.createIndex(
    { user_id: 1, created_at: -1 },
    { background: true, name: "idx_user_date" }
)

// Частковий індекс — тільки для активних замовлень
db.orders.createIndex(
    { created_at: -1 },
    {
        partialFilterExpression: { status: { $in: ["pending", "processing"] } },
        name: "idx_active_orders_date"
    }
)

// TTL індекс для автоматичного видалення застарілих сесій
db.sessions.createIndex(
    { expires_at: 1 },
    { expireAfterSeconds: 0, name: "ttl_sessions" }
)

// Перевірка використання індексів
db.orders.aggregate([
    { $indexStats: {} }
]).forEach(stat => {
    if (stat.accesses.ops === 0) {
        print("UNUSED INDEX: " + stat.name)
    }
})

background: true дозволяє створювати індекси без блокування бази. У MongoDB 4.2+ це поведінка за замовчуванням.

Explain та оптимізація запитів

// Аналіз плану виконання запиту
db.orders.find({ user_id: "507f1f77bcf86cd799439011", status: "pending" })
    .explain("executionStats")

// Ключові поля в executionStats:
// - stage: "COLLSCAN" означає повне сканування колекції — потрібен індекс
// - stage: "IXSCAN" — використовує індекс, хорошо
// - nReturned vs totalDocsExamined — чим ближче до співвідношення 1:1, тим кращий індекс
// - executionTimeMillis — час виконання

Включення профайлера для пошуку повільних запитів:

// Профілювати запити > 100ms
db.setProfilingLevel(1, { slowms: 100 })

// Перегляд повільних запитів
db.system.profile.find(
    { millis: { $gt: 100 } },
    { ns: 1, command: 1, millis: 1, ts: 1 }
).sort({ millis: -1 }).limit(20)

// Вимкнути профайлер (впливає на продуктивність!)
db.setProfilingLevel(0)

Replica Set: налаштування та моніторинг

// Ініціалізація replica set
rs.initiate({
    _id: "rs0",
    members: [
        { _id: 0, host: "mongo1:27017", priority: 2 },
        { _id: 1, host: "mongo2:27017", priority: 1 },
        { _id: 2, host: "mongo3:27017", arbiterOnly: true }
    ]
})

// Статус репліцірування
rs.status()

// Лаг реплики (критично: якщо oplog переповниться — реплика втратить синхронізацію)
rs.printSecondaryReplicationInfo()

// Розмір oplog (повинен охоплювати декілька годин операцій)
rs.printReplicationInfo()
// oplog size: 5760MB
// log length start to end: 14400 secs (4 hrs)
// Якщо менше 4–6 годин — збільшити:
db.adminCommand({ replSetResizeOplog: 1, size: 10240 }) // 10 GB

Резервне копіювання

mongodump — для баз розміром до декількох ГБ:

# Бекап з точкою консистентності на replica set
mongodump \
  --uri="mongodb://backup_user:password@mongo1:27017,mongo2:27017/mydb?replicaSet=rs0" \
  --readPreference=secondary \
  --oplog \
  --gzip \
  --out=/backups/dump_$(date +%Y%m%d_%H%M)

# Відновлення
mongorestore \
  --uri="mongodb://admin:password@localhost:27017" \
  --gzip \
  --oplogReplay \
  /backups/dump_20250101_0300

mongodump з --oplog блокує читання лише на secondary — для продакшену завжди беруть бекап з secondary.

Для великих баз (>100 ГБ) — снімки файлової системи (LVM, AWS EBS Snapshot) швидше фізично.

WiredTiger: компактифікація

MongoDB (WiredTiger) не повертає звільнене місце ОС автоматично. Після масового видалення документів — запустити compact:

// Компактифікація конкретної колекції
// УВАГА: блокує базу під час виконання!
db.runCommand({ compact: "orders" })

// На replica set — компактифікувати послідовно на secondary, потім переключити primary
// Запускати під час обслуговування

Перевірити оверхед до та після:

const stats = db.orders.stats({ scale: 1024 * 1024 })
console.log({
    dataSize: stats.size.toFixed(1) + ' MB',
    storageSize: stats.storageSize.toFixed(1) + ' MB',
    overhead_pct: ((1 - stats.size / stats.storageSize) * 100).toFixed(1) + '%'
})

Управління користувачами

use mydb

// Створення користувача додатку
db.createUser({
    user: "app_user",
    pwd:  "strong_password",
    roles: [
        { role: "readWrite", db: "mydb" }
    ]
})

// Тільки для читання для аналітики
db.createUser({
    user: "analytics",
    pwd:  "analytics_password",
    roles: [
        { role: "read", db: "mydb" }
    ]
})

// Список користувачів
db.getUsers({ showCredentials: false })

Пулінг з'єднань

Mongoose (Node.js) за замовчуванням відкриває 5 з'єднань. Для високонавантажених додатків:

mongoose.connect(process.env.MONGO_URI, {
    maxPoolSize:     50,  // максимум з'єднань у пулі
    minPoolSize:     5,
    serverSelectionTimeoutMS: 5000,
    socketTimeoutMS: 45000,
    connectTimeoutMS: 10000
})

Для PHP (розширення MongoDB):

$client = new MongoDB\Client(
    "mongodb://app_user:password@mongo1:27017,mongo2:27017/mydb",
    ["replicaSet" => "rs0", "readPreference" => "secondaryPreferred"],
    ["typeMap" => ["root" => "array", "document" => "array"]]
);

Моніторинг через mongostat та mongotop

# Статистика операцій у реальному часі (щосекунди)
mongostat --uri="mongodb://admin:password@localhost:27017" --discover

# Топ колекцій за часом читання/запису
mongotop --uri="mongodb://admin:password@localhost:27017" 5

# Ключові метрики для моніторингу в Prometheus (через mongodb_exporter):
# - mongodb_ss_globalLock_currentQueue_total > 0 — черга блокувань
# - mongodb_ss_connections_current vs maxIncomingConnections
# - replication lag на secondary
# - opcounters: insert/query/update/delete за секунду