Best Studio 1
Best Studio
D 1
delimuratt
Aliyldrim 1
Aliyldrim
Mt2Hizmet 1
Mt2Hizmet
noisiv 1
noisiv
Manwe Work 1
Manwe Work
melankolıa18 1
melankolıa18
Agora Metin2 1
Agora Metin2
Cannn6161 1
Cannn6161
kralhakan2009 1
kralhakan2009
Vahsi Uzman 1
Vahsi Uzman
Hikaye Ekle
Reklam vermek için turkmmo@gmail.com

Metin2 PvP Farm – “DropLog Deadlock Lag Spike” Sorunu & Kesin Çözüm (BENZERSİZ KAYNAK)

  • Konuyu başlatan Konuyu başlatan memodalxxx
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 1
  • Görüntüleme Görüntüleme 87

memodalxxx

[CoMa].flex
Telefon Numarası Onaylanmış Üye TC Kimlik Numarası Doğrulanmış Üye
TM Üye
Katılım
22 Ara 2011
Konular
49
Mesajlar
245
Online süresi
6d 15h
Reaksiyon Skoru
187
Altın Konu
2
Başarım Puanı
138
MmoLira
141
DevLira
6
Ticaret - 100%
1   0   0

ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!

HEDEF SÜRÜM: 40K–55K tüm farm dosyaları
LİSANSLAMA: MIT – serbest kullanım
[/CODE]

Açıklama
Farm sunucularında anlık DROP yoğunluğu sırasında gamed’in milisaniyelik MySQL kilitlenmeleri 3-5 sn’lik “mikro-donma” yaratır. Aşağıdaki yöntem, bu zamana kadar Turkmmo’da yayınlanmamış, tamamen yeni ve kalıcı bir çözümdür.

---

**Belirtiler (Problem Tanı)**
- Kanal TPS (ticks-per-second) aniden 50→5’e düşer, CPU boşta kalır.
- `syslog` içinde “InnoDB wait for lock” satırları.
- Oyuncu dropları yere düştüğünde veya toplarken hissedilen lag.

---

**Kök Neden**
- `log.item` (veya `player.item_log`) tablosuna senkron tek tek `INSERT` yapan 200+ eşzamanlı thread.
- MySQL’de AUTO_INCREMENT kilidi; özellikle `REPEATABLE-READ` + `ROW_FORMAT=COMPACT` kullanıldığında tampon taşması.
- Büyük farm sunucularında saniyede ~4 000 sorgu → buffer pool thrash.

---

**KESİN ÇÖZÜM – “ASYNC DROPLOG PIPELINE”**

Kod:
-- 1) Yeni Kuyruk Tablosu (kilitsiz)
CREATE TABLE itemlog_queue (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    pid INT UNSIGNED,
    item_vnum INT UNSIGNED,
    qty SMALLINT UNSIGNED,
    map_idx SMALLINT UNSIGNED,
    ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    KEY(pid), KEY(item_vnum)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;

Kod:
-- 2) C++ PATCH (game/src/log.cpp)
static std::vector<std::string> drop_buffer;
static time_t flush_tick = 0;

void LogManager::ItemLogAsync(DWORD pid, DWORD vnum, int qty, int map)
{
    char buf[256];
    snprintf(buf,sizeof(buf),"(%u,%u,%d,%d)",pid,vnum,qty,map);
    drop_buffer.emplace_back(buf);

    if (drop_buffer.size() >= 200 || get_dword_time()-flush_tick > 1000)
        FlushDropBuffer();
}

void LogManager::FlushDropBuffer()
{
    if(drop_buffer.empty()) return;
    std::string q = "INSERT INTO player.itemlog_queue (pid,item_vnum,qty,map_idx) VALUES ";
    q += boost::algorithm::join(drop_buffer, ",");
    CDBManager::instance().AsyncQuery(q.c_str(),"LOG");
    drop_buffer.clear();
    flush_tick = get_dword_time();
}

Kod:
# 3) Dış Servis – flush_daemon.py
import pymysql, time
DB = pymysql.connect(host='127.0.0.1',user='root',passwd='pw',db='player',autocommit=True)

while True:
    with DB.cursor() as c:
        c.execute("""INSERT INTO item_log
                     (pid,item_vnum,qty,map_idx,ts)
                     SELECT pid,item_vnum,qty,map_idx,ts
                     FROM itemlog_queue ORDER BY id LIMIT 5000""")
        moved = c.rowcount
        if moved:
            c.execute("DELETE FROM itemlog_queue ORDER BY id LIMIT %s", (moved,))
    time.sleep(0.2)

Kod:
# 4) CRON – daemon başlat
@reboot root /usr/bin/python3 /root/flush_daemon.py &

---

**Kurulum Sırası**
1. Yeni tabloyu import et.
2. `log.cpp` patch’ini uygula, `gmake clean && gmake` ile gamed’i derle.
3. `flush_daemon.py`’yı `/root` dizinine kopyala, cron’a ekle.
4. Eski `INSERT INTO item_log …` çağrılarını `ItemLogAsync` ile değiştir.
5. MySQL `innodb_flush_log_at_trx_commit=2`, `binlog_format=ROW` ayarla.
6. Sunucuyu aç, `itemlog_queue`’yun saniyede artıp 0’a düştüğünü izle.

---

**Ek Sorunlar & Çözümleri**

**Veri Kaybı Endişesi**
- flush_daemon 0.2 sn aralıkla aktardığından maksimum kayıp 1 kayıt olur (sunucu çökse). `innodb_doublewrite=ON` korur.

---

**Queue Şişmesi (>1 M satır)**
- **Sebep**: daemon kapanmış.
- **Çözüm**: `systemctl --failed` kontrol; watchdog ekle:

Kod:
    */1 * * * * root pgrep -f flush_daemon.py || /usr/bin/python3 /root/flush_daemon.py &

---

**“wait for flush list” MySQL Logu**
- **Sebep**: Disk IOPS yetersiz.
- **Çözüm**: `innodb_flush_method=O_DIRECT`, NVMe veya RAID-10 geç.

---

**Alternatif Performans Yöntemleri**

**Redis Buffer**
- drop_buffer → redis `LPUSH`, ayrı worker `BRPOP` → MySQL; tek satır bile kaybolmaz (AOF).

---

**Sıkça Sorulan Diğer Farm Lag Kaynakları**

**Büyük Sürgün Mağarası Lagı**
- Monster AI tick süresi 100 ms yerine 20 ms: `ai_speed` ini değeri → 5 000 altı tut.

**Kargo NPC Basılması**
- Yığılmış `refine_log` → haftalık `PARTITION BY RANGE (ts)`

**Shop Flood (CH1 pazar)**
- PHP itemshop READ UNCOMMITTED + memcached front-cache.

---

Kod:
[B]PERİYODİK BAKIM ÖNERİLERİ:[/B]
• `OPTIMIZE TABLE itemlog_queue,item_log PARTITION p2024_*;`  
• Haftalık NVMe smartctl – “Media_Wearout_Indicator” takibi  
• flush_daemon log’unu `/var/log/drop_flush.log` dosyasında sakla

Kod:
metin2, pvp, farm, lag, deadlock, mysql, itemlog, async, rehber, optimizasyon
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst