Arka Plan
Yetkili Teramind iş ortağı olarak Türkiye genelinde kurumsal Teramind kurulumlarını yönetiyoruz. Yönettiğimiz en büyük on-site kurulumlardan biri, özel bir Teramind sunucusunda yaklaşık 1.500 aktif kullanıcıya hizmet vermektedir.
Mayıs 2026'nın son haftasında bu ortamda eş zamanlı iki belirti ortaya çıktı ve durum hızla kritik bir olaya dönüştü.
Belirtiler
1. tmsrv Crash Loop
Teramind sunucu süreci (tmsrv) sürekli çöküp yeniden başlıyordu. Her çöküşten önce bir SIGABRT sinyali geliyordu — bu, sürecin dışarıdan kill sinyali almak yerine kendi kendini kasıtlı olarak durdurduğu anlamına geliyordu.
2. work_time Eksik Raporlanması
Panolardaki çalışan çalışma süresi verileri ciddi ölçüde eksik görünüyordu. Açıkça aktivite gösteren oturumlar sıfır ya da sıfıra yakın üretken süre kayıt ediyordu. İlk bakışta izleme politikası yanlış yapılandırması gibi görünüyordu.
Her iki belirtinin aynı anda ortaya çıkması, ortak bir nedenden kaynaklandıklarına işaret eden ilk sinyaldi.
İlk Müdahale: TMU 878
Teramind destek ekibiyle iletişime geçtik. Önerleri, çeşitli tmsrv kararlılık sorunlarını ele alan TMU 878 bakım güncellemesini uygulamaktı.
TMU 878'i uyguladık. Crash loop devam etti.
Güncelleme davranışı hiç değiştirmedi. Bu, kök nedenin TMU 878'in çözmek için tasarlanmadığı bir şey olduğu ve bunu kendimizin bulması gerektiği anlamına geliyordu.
Kök Nedenin Tespiti
Çöken tmsrv sürecinden bir core dump aldık ve stacktrace'i analiz ettik.
Çöküş, flush_log_and_abort() çağrısını yapan BackgroundWorker::threadFunc() içinde başlıyordu:
#4 flush_log_and_abort()
#5 teramind::server::BackgroundWorker::threadFunc()
#6 libboost_thread.so.1.74.0
#7 start_thread
flush_log_and_abort(), bekleyen log/veri yazımlarını tamamlayıp ardından abort() çağıran dahili bir Teramind fonksiyonudur. Süreç, bir veritabanı yazma hatası veya kısıtlama ihlali gibi kurtarılamaz bir durumla karşılaştığında tetiklenir.
Dikkatimizi veritabanına çevirdik.
Integer Overflow
PostgreSQL şemasını incelerken en yüksek trafikli tablolardaki kolon tiplerini kontrol ettik. mon_mail_attachment tablosu, Teramind ajanları tarafından yakalanan her e-posta eki olayını depolar.
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'mon_mail_attachment'
AND column_name = 'mon_mail_attachment_id';
Sonuç: integer — maksimum değeri 2.147.483.647 olan işaretli 32-bit integer.
Ardından mevcut sequence değerini kontrol ettik:
SELECT last_value FROM mon_mail_attachment_mon_mail_attachment_id_seq;
Sequence tavana ulaşmıştı. mon_mail_attachment tablosuna yapılan her yeni INSERT integer overflow nedeniyle başarısız oluyordu; BackgroundWorker kurtarılamaz hatayı yakalayıp flush_log_and_abort() çağırıyordu ve tmsrv yeniden başlıyordu — ancak bir sonraki e-posta eki olayında tekrar çöküyordu.
work_time eksik raporlanması bir yan etkiydi: veri kalıcılığından sorumlu arka plan çalışanı döngü ortasında çöktüğünde, o pencere için tamponlanmış üretkenlik metriklerini de düşürüyordu.
1.500 kullanıcı ve aktif e-posta izlemeyle bu tablo ayda yaklaşık 2–5 milyon satır biriktirir. 32-bit limit her zaman dolacaktı — sadece yeterince uzun sürdü ki kimse daha önce bununla karşılaşmamıştı.
Fix
TMU 878, mon_mail_attachment_id kolonunun veri tipini değiştirmemişti. Fix tek satırlık bir şema migrasyonuydu:
ALTER TABLE mon_mail_attachment
ALTER COLUMN mon_mail_attachment_id TYPE bigint;
bigint, maksimum değeri 9.223.372.036.854.775.807 olan işaretli 64-bit integer'dır — herhangi bir gerçekçi Teramind kurulumu için pratikte sınırsızdır.
Bu işlemi 31 Mayıs 2026, yaklaşık saat 22:00'de uyguladık (ajan kesintisi gerektirmeden, mesai sonrası — modern PostgreSQL sürümleri bunu tam tablo yeniden yazımı olmadan yalnızca metadata işlemi olarak yürütür).
Anlık sonuç:
- tmsrv crash loop durdu
- Ajan bağlantıları dakikalar içinde stabilleşti
- work_time verileri bir sonraki raporlama döngüsünde normale döndü
Neden Sıfır Kesinti?
PostgreSQL 12+ sürümlerinde, tür aralığına referans veren check kısıtlaması bulunmayan bir integer kolonunu bigint olarak değiştirmek yalnızca katalog değişikliğidir. PostgreSQL, diski üzerindeki tabloyu yeniden yazmaz — yalnızca tip metadatasını günceller. Bu, migrasyon işleminin tablo boyutundan bağımsız olarak milisaniyeler içinde tamamlandığı ve bakım penceresi gerektirmediği anlamına gelir.
Az Kalsın Felaket
Fix 31 Mayıs Cumartesi günü uygulandı. 2 Haziran Pazartesi, resmi tatil sonrasındaki ilk iş günüydü.
Bunu proaktif olarak yakalamış ve çözmüş olmasaydık müşteri, uzun bir hafta sonu tatilinin ardından Pazartesi sabahı Teramind panolarını açtığında şunlarla karşılaşacaktı:
- Tüm tatil dönemi için eksik ajan verileri
- Sıfır değer gösteren üretkenlik raporları
- Eksik veriler nedeniyle yanlış tetiklenen davranış uyarıları
Bu panolara güvenen yönetimin bulunduğu 1.500 kullanıcılı bir kurulumda bu ciddi bir tırmanmaya yol açardı. Zamanlama durumu daha da kötüleştiriyordu: tatil sonrası Pazartesi sabahı açılan bir destek talebi doğru kişilere ulaşmak için saatler alırdı.
Diğer Kurulumlarda Aynı Sorunu Önlemek
Önemli e-posta izleme hacmiyle on-site Teramind kurulumu çalıştırıyorsanız, mon_mail_attachment_id kolonunuzun hâlâ integer tipinde olup olmadığını kontrol edin:
SELECT
column_name,
data_type,
(SELECT last_value
FROM mon_mail_attachment_mon_mail_attachment_id_seq) AS current_seq,
2147483647 AS int_max,
ROUND(
(SELECT last_value FROM mon_mail_attachment_mon_mail_attachment_id_seq)::numeric
/ 2147483647 * 100, 2
) AS pct_used
FROM information_schema.columns
WHERE table_name = 'mon_mail_attachment'
AND column_name = 'mon_mail_attachment_id';
data_type değeri integer ve pct_used %70'in üzerindeyse, bir sonraki yüksek hacimli dönemden önce migrasyonu uygulayın:
ALTER TABLE mon_mail_attachment
ALTER COLUMN mon_mail_attachment_id TYPE bigint;
Aynı risk, 32-bit sequence kullanan diğer yüksek hacimli olay tablolarında da geçerlidir. Yoğun kurulumlarda denetlemeye değer tablolar:
| Tablo | Risk Faktörü |
|---|---|
mon_mail_attachment |
Yüksek (her ek = 1 satır) |
mon_web_file |
Orta–Yüksek (dosya yüklemeleri/indirmeleri) |
mon_keystroke |
Yoğun yazma ortamlarında yüksek |
mon_screen |
Orta (ekran görüntüsü olayları) |
Veri Büyümesi Yönetimi
Tamamlayıcı bir önlem olarak, büyük on-site kurulumlara otomatik temizleme daemon'u deploy ediyoruz. Daemon, Teramind'in yerleşik tm.pl aracını kullanarak günlük çalışır ve 12 aydan eski olay verilerini siler:
/usr/local/teramind/scripts/tm.pl \
-func remove_user_data_ex \
-keep_months 12 \
-no_disk_check
Terabi node'larına proxy yapan Master sunucularında -no_disk_check bayrağı önemlidir — bu bayrak olmadan betik, disk alanının sorun olmadığı durumlarda bile disk alanı kontrol hatasıyla iptal olabilir.
Bu, bigint migrasyonu ihtiyacını ortadan kaldırmaz (1.500 kullanıcıyla 12 aylık veri hâlâ yüz milyonlarca satır üretir), ancak sınırsız büyümeyi önler ve uzun vadede veritabanı performansını sağlıklı tutar.
Teramind'e İlettiğimiz Bulgular
Olayın ardından Teramind destek ekibine ayrıntılı bir rapor gönderdik. Temel noktalar:
- TMU 878 bu sorunu çözmedi.
mon_mail_attachment_idiçininteger → bigintmigrasyonu güncellemenin içinde yer almıyordu. - Bu migrasyonun resmi bir TMU sürümüne dahil edilmesini öneriyoruz — kurulumların standart güncelleme yoluyla yamalanabilmesi için.
- Mevcut on-site kurulumların proaktif olarak denetlenmesi gerekiyor — yoğun e-posta izlemeyle yıllardır Teramind çalıştıran herhangi bir müşteri potansiyel risk altındadır.
Özet
| Belirti | tmsrv crash loop + work_time eksik raporlanması |
| Kök neden | mon_mail_attachment_id 32-bit integer max'a ulaştı (2.147.483.647) |
| Vendor fix | TMU 878 — sorunu çözmedi |
| Gerçek fix | ALTER COLUMN mon_mail_attachment_id TYPE bigint |
| Kesinti süresi | Sıfır (PostgreSQL yalnızca katalog işlemi) |
| Etkilenen kullanıcı | ~1.500 |
| Fix süresi | Kök neden tespit edildikten sonra ~15 dakika |
On-site Teramind kurulumu yönetiyorsanız ve bu tanıdık geliyorsa, yukarıdaki denetim sorgusunu çalıştırın. Migrasyon güvenli, hızlı ve kalıcıdır.
Türkiye'deki Teramind kurulumları için — lisans, kurulum veya sürekli yönetim — iletişime geçin.