MySQL'de Mevcut Tabloya Partition Eklemek
Selamlar, bu yazıda MySQL'de zaten production'da çalışan bir tabloya nasıl partition eklendiğine bakacağız. Tabloyu sıfırdan yaratmak kolay, herkes onu yapıyor; asıl mesele yıllardır şişen bir sales ya da logs tablosuna dokunup işin ortasında üretimi yere yatırmamak. Lafı uzatmadan başlayayım.
Partition'lar sihirli değil; aslında MySQL'in tabloyu birden fazla fiziksel parçaya bölüp WHERE koşuluna göre sadece ilgili parçayı taraması demek. Tarih bazlı raporlamada (RANGE) ya da hash dağıtımında (HASH/KEY) ALTER TABLE ile partition eklemek, tabloyu yeniden yaratmaya göre çoğu zaman çok daha az can yakar.
Neden Yeni Bölüm Eklemek Gerekir?
PARTITION BY RANGE (YEAR(sale_date)) ile bölünmüş bir tablo, takvim ilerledikçe yeni yıl için yeni bir bölüme ihtiyaç duyar. HASH/KEY tabloları ise veri büyüdükçe yeniden dağılmak ister. Her iki durumda da çözüm tabloyu DROP edip yeniden yaratmak değil; ALTER TABLE ... ADD PARTITION ya da REORGANIZE PARTITION.
Bence en kritik nokta şu: tabloyu kurarken ileriyi düşünüp MAXVALUE ile bir p_future catch-all bölümü koymak, ileride hayatınızı kurtarır. Koymadıysanız da çare var, ama dolambaçlı.
RANGE Tablosuna Yeni Yıl Eklemek
Diyelim ki tablomuz şöyle yaratılmış olsun:
CREATE TABLE sales (
id BIGINT NOT NULL,
sale_date DATE NOT NULL,
amount DECIMAL(10,2),
PRIMARY KEY (id, sale_date)
)
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
2025 için bölüm açmak istiyoruz. p_future zaten 2025 verisini yutuyor; doğrudan ADD PARTITION çalışmaz çünkü MAXVALUE'dan büyük yeni bir aralık tanımlayamazsınız. Bu yüzden mevcut bölümü ikiye ayırıyoruz:
ALTER TABLE sales
REORGANIZE PARTITION p_future INTO (
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
REORGANIZE ne yapıyor? p_future içindeki kayıtları okuyup yeni iki bölüm arasında doğru kovaya yerleştiriyor. 2025 verisi p_future'a düşmüşse şimdi p2025'e taşınıyor. Tablo büyükse bu süre uzun, kilit ciddi olabilir.
Eğer tabloda hiç MAXVALUE yoksa - yani events tablosunun sonu en son p2024 VALUES LESS THAN (2025) ile bitiyorsa - işiniz çok kolay:
ALTER TABLE events
ADD PARTITION (PARTITION p2025 VALUES LESS THAN (2026));
Bu şekilde REORGANIZE derdine girmeden yeni aralık eklenir.
LIST Tablosuna Yeni Değer Kümesi
LIST partition'da işler daha rahat. Bölge bazlı bir tablo düşünün:
ALTER TABLE regions
ADD PARTITION (PARTITION p_asia VALUES IN (20, 21, 22));
Yeni bölge kodları geldiğinde böyle bir satır yetiyor. MAXVALUE benzeri bir tuzak yok burada; LIST kataloğa eklemek gibi.
HASH/KEY: Dikkat, Yeniden Dağıtım Var
HASH ya da KEY partition'da bölüm sayısını artırmak teknik olarak tek satır:
ALTER TABLE sessions ADD PARTITION PARTITIONS 4;
Ama buradaki tuzak şu: MySQL bütün veriyi yeni bölüm sayısına göre yeniden dağıtmak zorunda. Yani tablo 50 GB ise, fiilen 50 GB veri taşıyacak. Tecrübeyle söyleyebilirim ki bu komutu canlı saatlerde değil, gece pencerelerinde çalıştırmak lazım. Replication varsa lag'i de hesaba katın.
Sonucu Doğrulamak
Komutu attıktan sonra 'gerçekten oldu mu?' diye merak edersiniz. INFORMATION_SCHEMA zaten bunun için var:
SELECT
PARTITION_NAME,
PARTITION_DESCRIPTION,
TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = 'mydb'
AND TABLE_NAME = 'sales'
ORDER BY PARTITION_ORDINAL_POSITION;
TABLE_ROWS InnoDB'de tahminidir; kesin sayı için COUNT(*) lazım. Ama bölümlerin doğru sırada ve doğru aralıkla oluşup oluşmadığını görmek için bu sorgu yeter.
MySQL Event ile Aylık Otomasyon
Aylık logs tablosu tutuyorsanız her ay elinizle bölüm açmak sıkıcı. MySQL Scheduler bu işi devralabilir:
SET GLOBAL event_scheduler = ON;
CREATE EVENT add_monthly_log_partition
ON SCHEDULE EVERY 1 MONTH
STARTS '2026-06-01 00:00:00'
DO
ALTER TABLE logs
REORGANIZE PARTITION p_future INTO (
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
Tabii burada partition adını dinamik üretmek istiyorsanız PREPARE ve EXECUTE ile küçük bir prosedür yazmanız gerekir, çünkü EVENT gövdesinde değişken bölüm adı doğrudan çalışmaz. Bence ilk versiyonda bunu çok kurcalamayın; her ay manuel bir kontrol bile fena değil.
Sık Karşılaşılan Tuzaklar
- RANGE'de MAXVALUE'yu unutmak: Tablo kurulurken
p_futurekoymadıysanız, yeni yıl ekleyebilirsiniz ama eklemediğiniz aralığa düşen birINSERTdoğrudan hata verir. Sezon başında patlamasın. - HASH PARTITIONS n'i prime time'da çalıştırmak: Komut online değil; ciddi tablolarda saatler sürebilir, kilit tutar.
- REORGANIZE'in disk gereksinimini görmezden gelmek: İşlem sırasında MySQL ara tablo yaratır. Disk yarı doluysa ortada kalırsınız.
- Primary key'in partition kolonunu içermemesi:
PARTITION BY RANGE (YEAR(sale_date))kullanıyorsanızsale_datePK'nın içinde olmalı; yoksa MySQL daha tablo yaratırken homurdanır.
Kapanış
Özetle: LIST eklemek tek satır, HASH eklemek tek satır ama pahalı, RANGE'de MAXVALUE varsa REORGANIZE, yoksa düz ADD PARTITION. Şahsi kanaatim, tarih bazlı tablolarda en başından p_future koymak ve aylık ya da yıllık partition'ları MySQL Event'e devretmek - sonradan sıkışmaktan çok daha rahat. Umarım faydalı olur, bir sonraki yazıda görüşmek üzere.
