Veritabanı Yönetimi

    ProxySQL ile Veritabanı Yük Dengeleme

    ProxySQL ile MySQL trafiğini okuma ve yazma olarak ayırmanın uçtan uca kurulumu.

    11 dk okuma Güncellendi: 25 Ağustos 2026

    Replikasyon kurdun, elinde bir master ve iki replika var. Peki uygulama hangi sorguyu nereye gönderecek? Çoğu ekip bu soruyu uygulama kodunda çözmeye çalışır: bir "okuma bağlantısı", bir "yazma bağlantısı" tanımlanır ve geliştiricinin doğru olanı seçmesi beklenir. Bu yaklaşım ilk gün çalışır, altıncı ayda çalışmaz — çünkü biri unutur, bir framework kendi bağlantısını açar ve master gereksiz yere okuma trafiği altında ezilir. ProxySQL ile veritabanı yük dengeleme tam olarak bu kararı uygulamadan alıp araya konulan bir katmana devretmenin yoludur.

    ProxySQL, MySQL protokolünü konuşan bir ara sunucudur. Uygulama ona bağlanır, o da sorguyu inceleyip hangi arka uç sunucuya gideceğine karar verir. Bu rehberde ProxySQL'i kuracak, yönetim arayüzünün üç katmanlı yapılandırma mantığını çözecek, sunucuları hostgroup'lara ayıracak, okuma ve yazma sorgularını otomatik yönlendiren kurallar yazacak ve Galera kümesiyle nasıl birleştiğini göreceğiz. Sonunda ayrıca bağlantı çoğullama (multiplexing) ve en sık düşülen tuzaklara ayrı bir bölüm ayırdım.

    ProxySQL Tam Olarak Ne İşe Yarar#

    ProxySQL'in yaptığı iş "trafiği ikiye böl"den ibaret değildir. Uygulamadan gelen her sorguyu ayrıştırır, parmak izini (digest) çıkarır ve tanımladığın kurallara göre bir hostgroup'a yönlendirir. Bu sayede bir sorgunun nereye gideceğini uygulama kodunu değiştirmeden, çalışan sistem üzerinde saniyeler içinde değiştirebilirsin. Arka uç sunuculardan biri yanıt vermezse ProxySQL onu havuzdan çıkarır ve dönene kadar oraya sorgu göndermez; uygulama bu değişimden haberdar bile olmaz.

    İkinci büyük katkısı bağlantı yönetimidir. PHP-FPM gibi süreç başına bağlantı açan mimarilerde her istek yeni bir MySQL bağlantısı kurar; yoğun saatlerde bu, veritabanının max_connections sınırını zorlar ve klasik "Too many connections" hatasına yol açar. ProxySQL uygulamadan gelen yüzlerce bağlantıyı kabul eder ama arka uca çok daha az sayıda kalıcı bağlantı üzerinden gider — buna bağlantı çoğullama denir. Bu tek özellik bile, MySQL Too many connections hatası ile boğuşan bir sistemde tek başına kurulum sebebi olabilir. Üçüncü olarak ProxySQL sorgu önbelleği, sorgu yeniden yazma ve zamanlanmış bakım modu gibi işleri de üstlenebilir, ancak bu rehberde yük dengeleme çekirdeğine odaklanacağız.

    Kurulum ve Yönetim Arayüzüne Bağlanma#

    ProxySQL, Debian ve Ubuntu depolarında bulunur; güncel sürüm için üreticinin kendi deposunu eklemek daha sağlıklıdır. Kurulum sonrası servis iki port açar ve bu iki portun rolünü karıştırmamak kritik önemdedir.

    sudo apt update
    sudo apt install -y proxysql mysql-client
    sudo systemctl enable --now proxysql
    sudo systemctl status proxysql --no-pager
    
    PortKime açık olmalıGörev
    6033Uygulama sunucularıİstemcilerin bağlandığı MySQL portu
    6032Yalnızca localhostYönetim arayüzü, yapılandırma buradan yapılır

    6032 portunu asla dışarı açma; orası ProxySQL'in tüm yapılandırmasını ve kullanıcı bilgilerini barındıran yönetim kanalıdır. Yönetim arayüzüne yine bir MySQL istemcisiyle bağlanırsın:

    mysql -u admin -padmin -h 127.0.0.1 -P 6032 --prompt='ProxySQL Admin> '
    

    İlk iş varsayılan admin parolasını değiştirmektir:

    UPDATE global_variables SET variable_value='admin:CokGucluBirParola'
      WHERE variable_name='admin-admin_credentials';
    LOAD ADMIN VARIABLES TO RUNTIME;
    SAVE ADMIN VARIABLES TO DISK;
    

    Buradaki LOAD ... TO RUNTIME ve SAVE ... TO DISK komutları rastgele değildir. ProxySQL yapılandırmayı üç katmanda tutar: memory (yaptığın düzenlemelerin yazıldığı çalışma alanı), runtime (o an gerçekten uygulanan ayarlar) ve disk (yeniden başlatmada geri yüklenecek kalıcı kopya). Bir tabloyu güncellemek hiçbir şeyi değiştirmez; LOAD demeden ayar devreye girmez, SAVE demeden yeniden başlatmada kaybolur. Bu iki komutu unutmak, yeni başlayanların yaptığı bir numaralı hatadır.

    Arka Uç Sunucuları ve Hostgroup Tanımlama#

    ProxySQL sunucuları tek tek değil, hostgroup denen gruplar hâlinde düşünür ve kuralları bu gruplara yazarsın. Alışılmış kurgu iki gruptur: yazma grubu ve okuma grubu. Master 185.12.34.51, iki replika ise 185.12.34.52 ve 185.12.34.53 olsun.

    -- 10 = yazma grubu, 20 = okuma grubu
    INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight, max_connections, comment)
    VALUES
      (10, '185.12.34.51', 3306, 1000, 200, 'master'),
      (20, '185.12.34.52', 3306, 1000, 400, 'replika-1'),
      (20, '185.12.34.53', 3306, 1000, 400, 'replika-2');
    
    LOAD MYSQL SERVERS TO RUNTIME;
    SAVE MYSQL SERVERS TO DISK;
    

    weight alanı grup içindeki dağılım oranıdır; bir replika diğerinden güçlüyse ağırlığını yükselterek daha çok sorgu almasını sağlarsın. max_connections ise ProxySQL'in o sunucuya açacağı arka uç bağlantı üst sınırıdır ve sunucunun max_connections değerinin altında kalmalıdır.

    ProxySQL'in sunucuların sağlığını ölçebilmesi için arka uçlarda bir izleme kullanıcısı gerekir. Bu kullanıcıya veri okuma yetkisi vermek zorunda değilsin; yalnızca bağlanabilmesi ve read_only değerini görebilmesi yeterlidir.

    -- HER arka uç MySQL sunucusunda çalıştır
    CREATE USER 'proxysql_monitor'@'185.12.34.50' IDENTIFIED BY 'IzlemeParolasi';
    GRANT USAGE, REPLICATION CLIENT ON *.* TO 'proxysql_monitor'@'185.12.34.50';
    

    Ardından ProxySQL yönetim arayüzünde bu kullanıcıyı tanıt:

    UPDATE global_variables SET variable_value='proxysql_monitor' WHERE variable_name='mysql-monitor_username';
    UPDATE global_variables SET variable_value='IzlemeParolasi'  WHERE variable_name='mysql-monitor_password';
    LOAD MYSQL VARIABLES TO RUNTIME;
    SAVE MYSQL VARIABLES TO DISK;
    

    Klasik master-replika kurulumunda gruplar arası geçişi elle yönetmene gerek yok. mysql_replication_hostgroups tablosuna tek bir satır eklersen ProxySQL, sunucuların read_only değerine bakarak hangisinin yazma grubunda olacağına kendisi karar verir:

    INSERT INTO mysql_replication_hostgroups (writer_hostgroup, reader_hostgroup, comment)
    VALUES (10, 20, 'master-replika otomatik takip');
    LOAD MYSQL SERVERS TO RUNTIME;
    SAVE MYSQL SERVERS TO DISK;
    

    Bu satırdan sonra bir replikayı read_only=0 yapıp master'ı read_only=1 yaptığında ProxySQL rolleri saniyeler içinde takas eder. Replikasyon kurulumunu henüz yapmadıysan MySQL replikasyon kurulumu yazısı bu rehberin ön adımıdır.

    Uygulama Kullanıcılarını Tanımlama#

    ProxySQL, uygulamanın bağlanacağı kullanıcıları kendi tablosunda tutar ve arka uca giderken aynı kimlikle bağlanır. Yani kullanıcı hem MySQL sunucularında hem de ProxySQL'de tanımlı olmalıdır ve parolalar birebir aynı olmalıdır.

    -- ProxySQL yönetim arayüzünde
    INSERT INTO mysql_users (username, password, default_hostgroup, transaction_persistent, max_connections)
    VALUES ('uygulama', 'UygulamaParolasi', 10, 1, 500);
    
    LOAD MYSQL USERS TO RUNTIME;
    SAVE MYSQL USERS TO DISK;
    

    default_hostgroup değerini yazma grubu yapmak önemlidir. Hiçbir kurala uymayan bir sorgu bu gruba gider; varsayılanı okuma grubu yaparsan, tanımadığın bir yazma sorgusu replikaya düşer ve hata alırsın. transaction_persistent=1 ise bir transaction başladığında tüm sorguların aynı sunucuda kalmasını sağlar; bunu kapatmak, açık bir transaction'ın ortasında sorgunun başka makineye gitmesi gibi çok can sıkıcı hatalara yol açar.

    Uygulamanın bağlantı dizesini değiştirmen gerekir: artık 3306 yerine ProxySQL'in 6033 portuna bağlanacak. Test etmek için:

    mysql -u uygulama -pUygulamaParolasi -h 185.12.34.50 -P 6033 -e "SELECT @@hostname, @@read_only;"
    

    Yetki tarafında karışıklık yaşarsan, MySQL kullanıcılarının host bileşeninin nasıl eşleştiğini MySQL kullanıcı ve yetki yönetimi yazısında ayrıntılı anlattım; ProxySQL kullanırken arka uç kullanıcılarının ProxySQL sunucusunun IP'sinden bağlanabiliyor olması gerektiğini unutma.

    Sorgu Kuralları ile Okuma ve Yazma Ayrımı#

    Asıl yönlendirme işi mysql_query_rules tablosunda yapılır. Kurallar rule_id sırasına göre değerlendirilir; bir kural eşleşip apply=1 ise değerlendirme orada durur.

    INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
    VALUES
      -- 1) Transaction içindeki her şey master'da kalsın
      (10, 1, '^SELECT.*FOR UPDATE',        10, 1),
      (11, 1, '^SELECT.*LOCK IN SHARE MODE',10, 1),
      -- 2) Geri kalan tüm SELECT'ler okuma grubuna
      (20, 1, '^SELECT',                    20, 1);
    
    LOAD MYSQL QUERY RULES TO RUNTIME;
    SAVE MYSQL QUERY RULES TO DISK;
    

    Sıralamaya dikkat et: SELECT ... FOR UPDATE aslında bir kilit alır ve yazma niyetlidir, bu yüzden genel ^SELECT kuralından önce yakalanmalıdır. Aksi hâlde kilit isteyen sorgu replikaya gider ve uygulama sessizce yanlış davranır. INSERT, UPDATE ve DELETE için ayrı kural yazmana gerek yoktur; hiçbir kurala uymadıkları için default_hostgroup olan yazma grubuna düşerler.

    Bazı raporlama sorgularını özellikle tek bir replikaya yönlendirmek isteyebilirsin. Bunun için önce ayrı bir hostgroup tanımlar, sonra sorgu deseniyle eşleştirirsin:

    -- Ağır raporları 30 numaralı gruba (ayrı bir replika) gönder
    INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply)
    VALUES (30, 1, 'FROM siparis_ozet', 30, 1);
    LOAD MYSQL QUERY RULES TO RUNTIME;
    

    Kuralın gerçekten çalıştığını doğrulamanın en iyi yolu istatistik tablolarına bakmaktır:

    SELECT hostgroup, digest_text, count_star, sum_time
    FROM stats_mysql_query_digest
    ORDER BY sum_time DESC
    LIMIT 10;
    

    Bu çıktı, hangi sorgunun hangi gruba gittiğini ve toplam ne kadar süre harcadığını gösterir. Aynı zamanda ücretsiz bir yavaş sorgu raporu işlevi görür; kalıcı analiz için MySQL tarafında da slow query log yapılandırma adımlarını uygulamanı öneririm.

    Galera Kümesiyle Birlikte Kullanmak#

    Galera kümesinde tüm düğümler yazma kabul edebildiği için read_only bayrağına dayanan otomatik takip işe yaramaz. ProxySQL bu senaryo için ayrı bir tablo sunar: mysql_galera_hostgroups. Bu tablo, kümedeki düğümlerin wsrep_local_state durumunu izler ve Synced olmayan bir düğümü otomatik olarak devre dışı bırakır.

    INSERT INTO mysql_galera_hostgroups
      (writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup,
       active, max_writers, writer_is_also_reader, max_transactions_behind)
    VALUES (10, 12, 20, 90, 1, 1, 2, 100);
    
    LOAD MYSQL SERVERS TO RUNTIME;
    SAVE MYSQL SERVERS TO DISK;
    

    max_writers=1 ayarı burada özellikle önemlidir: kümedeki tüm düğümler yazabilse de, aynı satırlara farklı düğümlerden yazmak Galera'da çakışma kaynaklı geri almalara yol açar. Tek yazıcı bırakıp diğerlerini yedek yazıcı grubuna koymak, kümenin dayanıklılığını kaybetmeden bu çakışmayı ortadan kaldırır. writer_is_also_reader=2 ise yazıcı düğümün de okuma alabilmesini sağlar, ancak öncelik okuma gruplarındadır. Kümenin kendisini nasıl kuracağını Galera Cluster kurulumu yazısında adım adım bulabilirsin.

    İzleme, Bağlantı Havuzu ve Sık Yapılan Hatalar#

    Günlük kontrolde bakacağın ilk tablo bağlantı havuzudur. Hangi sunucuya kaç bağlantı açık, kaçı boşta ve son sağlık kontrolünde ne oldu, hepsi buradadır:

    SELECT hostgroup, srv_host, status, ConnUsed, ConnFree, ConnERR, Queries, Latency_us
    FROM stats_mysql_connection_pool;
    

    status sütunundaki değerler şunları anlatır:

    DurumAnlamı
    ONLINESunucu sağlıklı, trafik alıyor
    SHUNNEDHata verdiği için geçici olarak devre dışı, otomatik dönecek
    OFFLINE_SOFTYeni bağlantı almıyor, mevcut işlemleri bitiriyor
    OFFLINE_HARDTamamen kapalı, elle geri alınması gerekir

    Bakım yapacağın bir sunucuyu OFFLINE_SOFT yapmak, ProxySQL'in en sevdiğim özelliklerinden biridir: sunucu yeni sorgu almaz ama açık işlemler kesilmez, yani kimse hata görmez.

    Şimdi en sık düşülen tuzaklara gelelim. Birincisi, az önce bahsettiğim LOAD ve SAVE komutlarını atlamaktır. Tabloyu güncelleyip "neden değişmedi" diye saatlerce uğraşmak neredeyse bir geçiş töreni gibidir. İkincisi, bağlantı çoğullamanın oturum durumuyla çakışmasıdır. ProxySQL, arka uç bağlantılarını farklı istemciler arasında paylaştırır; ancak uygulama SET ile oturum değişkeni ayarlar, geçici tablo oluşturur ya da LOCK TABLES kullanırsa bu paylaşım güvensiz hâle gelir. ProxySQL bu durumları algılayıp o bağlantı için çoğullamayı otomatik kapatır, ama uygulaman her sorgudan önce SET NAMES gönderiyorsa havuz verimliliğin ciddi biçimde düşer. Bağlantı dizesinde karakter setini bir kez belirtmek çok daha doğrudur — bu konuda utf8mb4 geçişi yazısındaki istemci ayarları bölümü işine yarar.

    Üçüncü tuzak, replikasyon gecikmesini yok saymaktır. Uygulama bir kayıt ekleyip hemen ardından onu okumaya kalkarsa, okuma replikaya düşer ve kayıt henüz orada olmayabilir. Bunun iki çözümü var: ya bu tür "yazdıktan hemen sonra oku" akışlarını mysql_query_rules ile master'a sabitlersin, ya da max_transactions_behind değerini düşürerek geride kalan replikayı havuzdan çıkarttırırsın. Dördüncüsü ise ProxySQL sunucusunu tek nokta arıza hâline getirmektir. Araya koyduğun katman kendisi çökerse tüm veritabanı erişimi durur; bu yüzden ProxySQL'i uygulama sunucularının üzerine yerel olarak kurmak ya da iki ProxySQL örneğini sanal IP ile yedeklemek yaygın bir uygulamadır. Altyapıyı bu şekilde kurgularken sunucu yönetimi hizmetimiz mimari kararlarda ve kurulumda yanında olabilir.

    Sıkça Sorulan Sorular#

    ProxySQL ücretsiz mi#

    ProxySQL açık kaynak bir yazılımdır ve GPL lisansıyla ücretsiz olarak kullanılabilir; üretimde kullanmak için lisans satın alman gerekmez. Üretici firma yalnızca kurumsal destek ve danışmanlık paketleri için ücret alır. Yazılımın tüm özellikleri, sorgu kuralları ve Galera desteği dahil, ücretsiz sürümde mevcuttur.

    ProxySQL uygulamamı yavaşlatır mı#

    Araya bir katman koymak teorik olarak gecikme ekler ama pratikte çoğu kurulumda toplam gecikme düşer. Bunun sebebi bağlantı çoğullamadır: uygulama her istekte yeni bir MySQL bağlantısı kurup el sıkışma maliyeti ödemek yerine ProxySQL'in hazır havuzunu kullanır. ProxySQL'in kendi ek gecikmesi genelde mikrosaniyeler seviyesindedir ve okuma trafiğinin replikalara dağılmasıyla kazanılan performans bunu fazlasıyla karşılar.

    ProxySQL yerine ne kullanmalıyım#

    Alternatifler arasında MaxScale, HAProxy ve uygulama seviyesindeki sürücü tabanlı yönlendirme sayılabilir. HAProxy MySQL protokolünü anlamadığı için sorgu bazlı yönlendirme yapamaz, yalnızca TCP seviyesinde dağıtım yapar; yani okuma yazma ayrımını sana bırakır. MaxScale, ProxySQL'e en yakın alternatiftir ancak bazı sürümlerinde lisans kısıtları vardır. Sorgu farkındalığı ve bağlantı havuzu istiyorsan ProxySQL çoğu senaryoda en pratik seçimdir.

    ProxySQL yapılandırmasını nasıl kalıcı hâle getiririm#

    ProxySQL üç katmanlı yapılandırma kullanır ve yaptığın değişiklik varsayılan olarak yalnızca bellekte durur. Ayarı devreye almak için LOAD ... TO RUNTIME, yeniden başlatmalarda kaybolmaması için SAVE ... TO DISK komutlarını çalıştırman gerekir. Her iki komutu da değiştirdiğin tabloya göre yazarsın; sunucular için MYSQL SERVERS, kurallar için MYSQL QUERY RULES gibi.

    Bir replika geride kalırsa ProxySQL bunu fark eder mi#

    Fark eder, ancak bunu yapabilmesi için izleme kullanıcısının REPLICATION CLIENT yetkisine sahip olması ve mysql_servers tablosundaki max_replication_lag değerinin sıfırdan farklı ayarlanması gerekir. Bu değeri örneğin 30 saniye yaparsan, gecikmesi bu eşiği aşan replika otomatik olarak havuzdan çıkarılır ve gecikme kapandığında geri alınır. Galera kurulumlarında bunun karşılığı max_transactions_behind değeridir.

    ProxySQL çöktüğünde ne olur#

    Uygulama ProxySQL üzerinden bağlandığı için, ProxySQL durduğunda veritabanı erişimi de durur; bu yüzden onu tek nokta arıza hâline getirmemek gerekir. En yaygın iki çözüm şunlardır: ProxySQL'i her uygulama sunucusunun kendi üzerine kurmak, böylece bir örneğin çökmesi yalnızca o makineyi etkiler; ya da iki ProxySQL örneğini keepalived ile sanal bir IP arkasında yedeklemek. Yerel kurulum aynı zamanda ağ turunu da azalttığı için pek çok ekipte tercih edilir.

    Kapanış#

    ProxySQL, veritabanı trafiğini yönetme kararını uygulama kodundan çıkarıp tek bir kontrol noktasına taşır ve bu, ölçeklenmeye başlayan her sistemde çok kısa sürede karşılığını verir. Aklında kalması gereken alışkanlıklar şunlar: her yapılandırma değişikliğinden sonra LOAD ve SAVE komutlarını çalıştır, default_hostgroup değerini daima yazma grubu yap, SELECT ... FOR UPDATE gibi kilit alan sorguları genel ^SELECT kuralından önce yakala ve stats_mysql_connection_pool tablosunu düzenli olarak kontrol et. Bir de ProxySQL'in kendisini yedeklemeyi planla — araya koyduğun her katman, aynı zamanda yeni bir arıza noktasıdır.

    Bu mimariyi kurmak için yeterli kaynağa sahip sunuculara ihtiyacın olacak; okuma replikalarını ayrı makinelerde tutmak istiyorsan VDS ve bulut sunucu paketlerimiz esnek bir başlangıç sunar. Kurulumu, izleme kullanıcılarını ve kural setini kendin yönetmek istemiyorsan sunucu yönetimi hizmetimiz bu katmanı da üstlenir; trafiğin arttığı dönemlerde uygulama tarafını korumak için WAF çözümümüze de göz atabilirsin.

    ProxySQLMySQLYük Dengeleme

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.