Ana içeriğe geç

MongoDB Olası Sorunları ve Çözümleri

CentOS 7 üzerinde MongoDB kurulumunda hata alınırsa

Sebep/Neden: warning: /var/cache/yum/x86_64/7/MongoDB/packages/mongodb-org-mongos-4.2.13-1.el7.x86_64.rpm: Header V3 RSA/SHA1 Signature, key ID 058f8b6b: NOKEY

Retrieving key from https://www.mongodb.org/static/pgp/server-4.2.asc

Çözüm

Aşağıdaki dosyada gpgcheck=0 yapmak

sudo vi /etc/yum.repos.d/mongodb.repo
[MongoDB]
name=MongoDB Repository
baseurl=http://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/$basearch/
gpgcheck=0
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc

CentOS 8 üzerinde MongoDB kurulumunda hata alınırsa

Sebep/Neden

Eğer "systemctl status mongodb.service -l" komutunda aşağıdaki gibi bir çıktı görüyorsanız:

SELinux is preventing /usr/bin/mongod from read access on the file snmp.

Çözüm

Aşağıdaki komutları çalıştırın ve mongodb.service durumunu hatalar kaybolana kadar kontrol edin:

grep mongod /var/log/audit/audit.log | audit2allow -M mypol
semodule -i mypol.pp
grep ftdc /var/log/audit/audit.log | audit2allow -M mypol
semodule -i mypol.pp

/var/lib/mongodb yolunun çok fazla miktarda yer kaplaması

Sebep/Neden

Bu bir problem olmamakla birlikte bazı durumlarda yetersiz disk ve dolayısıyla sistem işleyişine etki edebilmektedir. Özellikle journaling açıksa ve replicaset'te çok node'lu yapı kullanılıyorsa bu durum görülebilir.

Çözüm

Çoklu Node kullanımlarda: Çalışan mongod servislerinden biri kapatılarak primary'nin bir başka sunucudaki mongo'ya geçmesi beklenir. Sonrasında /var/lib/mongodb yolundaki tüm dosyalar silinir. Mongod servisi baştan başlatıldığında otomatik senkronizasyon ile sadece gerekli dosyalar oluşturulacaktır. Operasyonlarda kesintiye yol açmaz.

Tek Node kullanımlarda: Operasyonlarda kesinti yapılarak gerçekleştirilebilir. Mevcut veritabanının yedeği alınır, çalışan manager durdurulur, veritabanı drop edilir, /var/lib/mongodb yolu temizlenir, mongo geri yüklenir, manager tekrar çalıştırılır.


Bir projenin ve içindeki proxy'lerin manuel olarak silinme ihtiyacı olursa

Sebep/Neden

Bu bir problem olmamakla birlikte bunlar manuel olarak silinmek istenirse uygulanabilir.

Çözüm

Çözüm için sırasıyla aşağıdaki adımlar izlenebilir:

1. Mevcut projelerdeki id'leri al ve string'e çevir:

var validProjectIds = db.project.find({}, {_id: 1}).toArray().map(function(item){ return item._id.toString(); });

2. API proxy'ler üzerinde gezerek karşılığı mevcut olmayan proje id'lerini bul:

var invalidProjectIds = [];
db.api_proxy.find({}).forEach(function(doc) {
if( doc.projectId && doc.projectId!=='admin' && !validProjectIds.includes(doc.projectId.toString())) {
if( !invalidProjectIds.includes(doc.projectId.toString())) {
invalidProjectIds.push(doc.projectId);
}
}
});

3. İlişkisi olmayan api_proxy'ları sil:

invalidProjectIds.forEach(function(invalidProjectId) {
db.api_proxy.deleteMany({projectId: invalidProjectId});
});

Bir projeye admin kullanıcısını proje sahibi olarak eklemek

Sebep/Neden

Bu bir problem olmamakla birlikte projeye hızlı erişim gerektiği durumlarda uygulanabilir.

Çözüm

// Apinizer veritabanına geçilir
use apinizerdb

// Aşağıdaki komut çalıştırılır ve gelen ObjectId değerinin içeriği alınır
db.role.find({name:"Project Owner"}, {_id:1})

// Alınan değer aşağıdaki komutta <OBJECT_ID> alanına yazılır ve <PROJECT_NAME> alanına istenilen proje adı yazılarak komut çalıştırılır
db.project.updateOne(
{ name:"<PROJECT_NAME>" },
{
$push: {
"projectMember.teamMemberList": {
userId: "admin",
roleList: [
{
$ref: "role",
$id: ObjectId("<OBJECT_ID>")
}
]
}
}
}
)

MongoDB Cluster'ındaki Node'un Hostname'i Değişecekse

uyarı
Çalışma Öncesi Dikkat Edilmesi Gerekenler:
  • Bu işlemler MongoDB replicaset'indeki hata tolerasyonuna dikkat edilerek yapılmalıdır aksi takdirde kesintiler yaşanabilmektedir (MongoDB (n-1)/2 tolerasyonu)
  • Bu tür bir işlem öncesinde tam bir sistem yedeği alınması önerilmektedir.

Sebep/Neden

MongoDB cluster'da hali hazırda çalışan bir node'un hostname'i değiştirildiğinde, bazı yapılandırmalar ve kimlik bilgileri eski hostname ile çakışabilmektedir. Bu yüzden bu işlemi yaparken replicaset'te hostname'i değiştirilecek node çıkartılıp hostname bilgisi değiştikten sonra eklenmelidir.

Çözüm

1. Çalışma Öncesi MongoDB Backup Alınır

Primary node'a bağlanılır ve Apinizer'ın MongoDB veritabanı yedeği alınır.

mongosh mongodb://localhost:25080 --authenticationDatabase "admin" -u "apinizer" -p
show dbs
use apinizerdb

# Veritabanındaki yüksek boyutlu koleksiyonlar kontrol edilir
db.getCollectionNames().map(name => ({storageSizeMB: (db.getCollection.stats().storageSize / (1024*1024)).toFixed(2), name: name})).sort((a,b) => a.storageSizeMB - b.storageSizeMB).forEach(printjson);

# Eğer yüksek boyutlu koleksiyon var ise ve yedek alınmak istemiyorsa --excludeCollection <Collection_Name> parametresi kullanılabilir
sudo mongodump --host localhost --port=25080 --username=apinizer --password=passwd -d apinizerdb --authenticationDatabase=admin --gzip --archive=/home/apinizer/mongodump/apinizer-backup-v<Apinizer Version>-<Date>--1.archive

2. Hostname'in Değişeceği Node MongoDB Replicaset'ten Çıkarılır

mongosh mongodb://localhost:25080 --authenticationDatabase "admin" -u "apinizer" -p
rs.status()

# Eğer sunucu primary node ise önce secondary'e çevrilir ve yeni primary'e bağlanılır (rs.stepDown())
rs.remove("<NODES_OLD_HOSTNAME>")
rs.status()

# Hostname'i değiştirilecek sunucuya bağlanılır mongodb servisi durdurulur
sudo systemctl stop mongod
sudo hostnamectl set-hostname <NODES_NEW_HOSTNAME>
sudo reboot

hostname
# /etc/hosts üzerinde 127.0.0.1 ip'sine karşılık eski hostname duruyorsa bu kısım yeni hostname ile değiştirilmelidir
sudo vi /etc/hosts
sudo systemctl start mongod

# Primary sunucuya bağlanılır ve hostname'i değişen node replica set'e dahil edilir
rs.add("<NODES_NEW_HOSTNAME>")

# Veri senkronizasyonunun tamamlanması beklenilir
rs.status()

Yarıda Kesilen Bir Silme İşleminin Kilitlediği Kaydın Kurtarılması

Sebep/Neden

Kimlik Bilgisi, Kurum ya da Portal Uygulaması gibi bağlı bir kaydı silerken Apinizer, aynı kayda ait iki silme işleminin çakışmasını önlemek için kısa süreli bir kilit tutar (bkz. Eş Zamanlı Silme). Kilidi tutan sunucu süreci silme işlemi tamamlanmadan (ör. beklenmedik bir sunucu yeniden başlatması) sonlanırsa kilit kendiliğinden açılmaz: kayıt kalıcı olarak "silme sürüyor" durumunda kalır ve sonraki her silme denemesi de aynı şekilde reddedilir. Bu bilinçli bir davranıştır — kaydın gerçek durumu (silme işleminin ne kadarının tamamlandığı) bilinmediği için kilidin kendiliğinden açılmasına izin vermek, yarım kalmış bir işlemin üzerine ikinci bir silme denemesinin binmesi riskini taşırdı.

Teşhis

Kilit lifecycle_deletion_barrier koleksiyonunda tutulur. Etkilenen kayda ait belge önce bulunur:

use apinizerdb

// <SUBJECT_TYPE> => CONSUMER (kimlik bilgisi) | ORGANIZATION (kurum) | APPLICATION (portal uygulaması)
// <SUBJECT_ID> => ilgili kaydın Mongo _id değeri
db.lifecycle_deletion_barrier.findOne({ _id: "<SUBJECT_TYPE>:<SUBJECT_ID>" })

Belgedeki alanlar durumu netleştirir:

AlanAnlamı
stateHELD ise kilit hâlâ tutuluyor demektir; RELEASED ise zaten serbesttir — bu durumda 409 yanıtının başka bir nedeni vardır.
operationIdKilidi tutan işlemin kimliğidir.
acquiredAtKilidin alındığı zamandır — üzerinden geçen süre, işlemin gerçekten yarıda kalıp kalmadığını değerlendirmede kullanılır.
acquiredByKilidi alan kullanıcı/hesaptır.
projectIdKaydın ait olduğu projedir (varsa).

acquiredAt üzerinden makul bir süre (ör. birkaç dakika) geçtiği ve o sırada sunucuda ilgili bir yeniden başlatma/kesinti yaşandığı doğrulandıysa işlem yarıda kalmış demektir.

Çözüm

İşlemin gerçekten sonlandığından emin olduktan sonra kilit elle serbest bırakılır:

db.lifecycle_deletion_barrier.updateOne(
{ _id: "<SUBJECT_TYPE>:<SUBJECT_ID>" },
{ $set: { state: "RELEASED", releasedAt: new Date() } }
)

Bu işlem yalnızca kilidi açar; kaydın kendisine dokunmaz. Kilit açıldıktan sonra silme isteği normal şekilde tekrar denenebilir ve o anki silme engelleri yeniden baştan değerlendirilir.

uyarı

Bu işlem veritabanına doğrudan müdahaledir ve yalnızca yetkili bir Apinizer yöneticisi tarafından, işlemin gerçekten sonlandığından emin olunduktan sonra uygulanmalıdır. Emin olunmadan uygulanması, hâlâ süren bir silme işlemiyle yeni bir silme denemesinin çakışmasına yol açabilir.