Tablo Kilidi Tuzağı
<p>B2B SaaS platformunuzun ilk günlerinde, üretim sunucunuzda <code>php artisan migrate</code> çalıştırmak milisaniyeler sürer. Ancak Smart Tech Devs’de platformunuz büyüdükçe, veritabanı tablolarınız da büyür. <code>activity_logs</code> veya <code>invoices</code> tablosu 50 milyon satıra ulaştığında, basit bir migration aniden felaket bir olaya dönüşebilir.</p>
<p>Sorgularınızın yavaşladığını düşündüğünüzü hayal edin; bu nedenle <code>status</code> sütununa yeni bir indeks eklemeye karar veriyorsunuz. Standart bir Laravel migration yazıyor ve dağıtımını yapıyorsunuz. Anında uygulamanız çevrimdışı oluyor. API istekleri zaman aşımına uğruyor, kullanıcılar 500 hataları alıyor ve arka plan görevleri çöküyor. Neden? Çünkü varsayılan olarak, PostgreSQL bir indeks oluşturmak için tabloyu özel bir kilitlemeye ihtiyaç duyar. İndeks tamamlanana kadar tüm <code>INSERT</code>, <code>UPDATE</code> ve <code>DELETE</code> işlemlerini fiziksel olarak engeller—50 milyon satırlık bir tabloda, bu işlem 10 dakika sürebilir.</p>
<h2>Çözüm: Eşzamanlı İndeks Oluşturma</h2>
<p>Sıfır kesinti süreli veritabanları tasarlamak için, indeksleri tabloyu kilitlemeden arka planda oluşturmamız gerekiyor. PostgreSQL, bu amaç için harika bir özellik sunar: <code>CREATE INDEX CONCURRENTLY</code>.</p>
<p>Eşzamanlı olarak bir indeks oluşturduğunuzda, PostgreSQL tabloyu iki ayrı tarama yapar. İndeksin toplamda oluşturulması daha uzun sürer, ancak indeks yapılandırılırken uygulamanızın tabloya normal şekilde okuma ve yazma işlemlerine devam etmesine olanak tanır.</p>
<h3>Laravel'de Eşzamanlı İndeks Uygulama</h3>
<p>Standart Laravel Blueprint yöntemleri (örn. <code>$table->index('status')</code>) yerel olarak eşzamanlı oluşturma desteği sağlamaz, çünkü bu özellik ham SQL gerektirir ve bir veritabanı işlemi içinde çalıştırılamaz.</p>
<p>50 milyon satırlık büyük bir tabloda sıfır kesinti süreli bir indeks dağıtma için mimari desen aşağıdaki gibidir.</p>
<pre><code>use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class AddStatusIndexToInvoicesTable extends Migration
{
/
- KRİTİK: Eşzamanlı indeksler bir işlem içinde oluşturulamaz.
- Migration sarma işlemini devre dışı bırakmalıyız.
*/
public $withinTransaction = false;
public function up(): void
{
// Arka planda indeksi oluşturmak için ham PostgreSQL komutunu çalıştır
DB::statement('
CREATE INDEX CONCURRENTLY IF NOT EXISTS invoices_status_idx
ON invoices (status);
');
}
public function down(): void
{
// Geri almak istersek indeksi eşzamanlı bir şekilde güvenle kaldır
DB::statement('
DROP INDEX CONCURRENTLY IF EXISTS invoices_status_idx;
');
}}
<h2>Migration Hatalarını Yönetme</h2>
<p>Eşzamanlı indeksler bir işlem dışında çalıştığından, indeks oluşturma işlemi başarısız olursa (örn. benzersiz kısıtlama ihlali nedeniyle), PostgreSQL'de "geçersiz" bir indeks bırakabilir. İndeks mevcut olur, ancak veritabanı, sorgular için bunu göz ardı eder.</p>
<p>Eğer bu olursa, migration'ı tekrar denemeniz yeterli olmayacaktır. Öncelikle <code>DROP INDEX CONCURRENTLY invoices_status_idx</code> komutunu çalıştırarak geçersiz nesneyi temizlemeniz, ardından temeldeki veri sorununu düzeltmeniz ve sonra migration'ı tekrar çalıştırmanız gerekir.</p>
<h2>Sonuç</h2>
<p>Dayanıklı yazılım inşa etmek, üretim verilerini dikkate almayı gerektirir. Çalışma saatleri içinde B2B tablolarınızı 10 dakika boyunca kilitleyemezsiniz. PostgreSQL’in eşzamanlı işlemlerini ustalıkla kavrayarak ve Laravel’in migration işlemlerini güvenle atlayarak, veritabanınızı ölçeklenebilir hale getirirken kesintisiz çalışma süresi garantisi sağlayabilirsiniz.</p>Kaynak: Orijinal Makale


