Canlı üretim veritabanlarında alternatif tablo


24

Çoğu "popüler" (MySQL, Postgres ...) veritabanı sistemi, canlı üretim veritabanlarında (tablo türlerini ekleme, silme veya değiştirme gibi) değişen tabloları nasıl işler?

Biliyorum doğru yolu yedekleme herşey zamanlama kesinti etmektir ve değişiklikleri daha sonra yapacağız.

Ancak ... herhangi bir mevcut veritabanı sistemi hiçbir şeyi durdurmadan bu çevrimiçi işlemlerin yapılmasını destekliyor mu? (belki de yalnızca değiştirilen / silinen bir sütuna başvuran sorguları geciktirmek)

Ve ben sadece ALTER TABLE...canlı çalışan bir veritabanında yaptığımda ne olur ? Bu olduğunda her şey durur mu? Veriler bozulabilir mi? vb.

Yine çoğu zaman Postgres veya MySQL'e atıfta bulunuyorum.

(Ve evet, ne zaman yapmalıydım "doğru yoldan" yapmadan önce, işleri destekledim, işin durgunluğunu planladım vs.) kirli "veya" hızlı, canlı ve kirli "şema değişikliklerini gerçekten destekleyen herhangi bir DB sistemi varsa)


Birisi az önce Facebook komut dosyasından MySQL için Çevrimiçi Şema Değişikliği önerdi ( burada bir eğitim ve burada kaynak koduyla ) ... bunu yapmak için "hacky" yöntemlerini bir dizi otomatikleştirmek için iyi bir yol gibi görünüyor ... bir şey üretimi andırıyor mu?


3
Not: Belirtilen "doğru yol", PostgreSQL'e değil, MySQL'e bağlıdır. PostgreSQL'deki "doğru yol", dahil olmasına rağmen, genellikle çok kolaydır. Kullanımı pg_reorgdaha zor senaryolarda yardımcı olabilir.
Sean

Bu konuda ayrıntılı bir videoya sahip olmayı çok isterdim, biri mümkün olduğunca çok sayıda stratejiyi açıklıyor.
Sandeepan Nath

Yanıtlar:


22

Bir ALTER TABLEPostgreSQL'de yayınladığınızda, dahil her şeyi engelleyen bir ACCESS EXCLUSIVEkilitlenecektirSELECT . Masa yeniden yazma, yeni gerektirmez Ancak, bu kilit oldukça brifing edilebilir UNIQUE, CHECKya da FOREIGN KEYkısıtlamalar vb pahalı bütün tablo taraması doğrulamak gerekir

Şüphe durumunda, genellikle sadece deneyebilirsiniz! PostgreSQL'deki tüm DDL işlemseldir, bu nedenle bir ALTER TABLEişlemi çok uzun sürerse iptal edip diğer sorguları tutmaya başlar. Çeşitli komutların gerektirdiği kilitleme seviyeleri kilitleme sayfasında belgelenmiştir .

Bazı normal yavaş işlemlerin, aksama süresi olmadan güvenli bir şekilde yapılması için hızlandırılabilir. Tabloyu varsa Örneğin, tve sütun değiştirmek istediğiniz customercode integer NOT NULLiçin textmüşteri kodları artık başlamalı tüm müşteri karar verdi çünkü X, sen yazabilirsiniz:

ALTER TABLE t ALTER COLUMN customercode TYPE text USING ( 'X'||customercode::text );

... ama bu yeniden yazmak için tüm masayı kilitlerdi. Böylece bir sütun ekleyerek yapar DEFAULT. Uzun kilitlenmeyi önlemek için birkaç adımda yapılabilir, ancak uygulamaların geçici çoğaltma ile başa çıkabilmesi gerekir:

ALTER TABLE t ADD COLUMN customercode_new text;
BEGIN;
LOCK TABLE t IN EXCLUSIVE MODE;
UPDATE t SET customercode_new = 'X'||customercode::text;
ALTER TABLE t DROP COLUMN customercode;
ALTER TABLE t RENAME COLUMN customercode_new TO customercode;
COMMIT;

Bu yalnızca engelleyecektir yazıyor için tişlem sırasında; kilit adı EXCLUSIVE, dışındakiSELECT her şeyi dışladığı için biraz aldatıcıdır ; Bu ACCESS EXCLUSIVEmod, kesinlikle her şeyi dışlayan tek moddur. Kilit modlarına bakınız . Bu işlemin gerektirdiği kilit güncellemesi nedeniyle kilitlenme geri dönme riski vardır ALTER TABLE, ancak en kötüsü tekrar yapmanız gerekecek.

Hatta o kilidi önlemek ve bir tetikleyici işlevi oluşturarak canlı şeyi yapabileceği to zaman bir INSERTveya UPDATEotomatik doldurur, gelir customercode_newdan customercode.

Aynı zamanda DBA'ların eşzamanlılık dostu bir şekilde daha yavaş çalışarak özel kilitleme sürelerini azaltmasına izin vermek için tasarlanmış CREATE INDEX CONCURRENTLYve benzeri yerleşik araçlar da vardır ALTER TABLE ... ADD table_constraint_using_index.

pg_reorgAracı veya halefi pg_repackyanı bazı tablo yeniden yapılandırılması işlemleri için kullanılabilir.


1
@Craig'in söylediği en önemli şey, “yeniden yazma gerektirmiyorsa” idi. Bir ALTER TABLE t ADD COLUMN i INTkilit kullanıldığında hızlı bir işlem (tipik olarak <1ms) kullanılır. Ancak, kilidin alınması bağlantıları sıraya sokabilir, bu yüzden "ücretsiz" değildir, ancak dünyanın MySQL'de yapmanız gerekenden daha iyidir. Bir NOT NULLkısıtlama eklemek kalbe olan için değil, daha zordur.
Sean,

pg_repackGeliştirilmiş halefi olan fikir birliği gibi görünüyor pg_reorg.
Erwin Brandstetter

İyi bir cevap, varsayılan (veya hesaplanan) bir sütunu eklemeyle ilgili daha az "engelleme" yolu, tamamen yeni bir tablo oluşturmaktır, eski tabloyu eklemek / güncellemek / silmek için engellemekle birlikte yeni olanı seçip doldurmaktır. Son olarak, eski tabloya seçme, silme ve yenisini eskiyle yeniden adlandırma için özel bir kısa kilit verin. Senaryonuza bağlı olarak, yeni olanı eskiyi engellemeden doldurmaya bile başlayabilirsiniz ve sadece farkı çözerken özel kilidi kilitlemeye başlayabilirsiniz (umarım sadece birkaç yeni kayıt ekleyerek)
jean

7

Percona, çevrimiçi şema değişikliklerini gerçekleştirmek için kendi aracıyla geldi

Bu araca pt-online-schema-change adı verilir.

Tetikleyicileri içerir, bu yüzden lütfen dokümanları dikkatlice okuyun.

Belgelere göre, yapılan başlıca işlemler

  • Sağlık kontrolleri
  • Chunking
  • Çevrimiçi şema değişikliği
    • Geçici tablo oluşturma ve değiştirme
    • Tablodan geçici tabloya değişiklikleri yakalayın
    • Tablodan geçici tabloya satır kopyalama
    • Tabloyu ve geçici tabloyu senkronize et
    • Masayı ve geçici masayı değiştir / yeniden adlandır
    • Temizlemek

teşekkürler, Facebook'un daha fazla güvenebileceğim yaklaşımının "çözülmüş" bir versiyonuna benziyor ...
NeuronQ

pt-online-schema-change kesinlikle kendi MySQL sunucunuzu kullanıyorsanız, bunu yapmanın tercih edilen yoludur. Percona Tools 2.2'den itibaren (ne yazık ki) AWS'de RDS / Aurora'yı desteklemiyorlar. pt-online-schema-change, kaynak tabloya satırları (MyISAM için düşük öncelikli) hedef table_temp'ye kopyalamak için bir tetikleyici ekler ve tüm satırlar kaynak ve hedef arasında senkronize olduğunda, tek bir hızlı kilitleme düşüşü yapar ve sonunda yeniden adlandırır tablolar.
phpguru

6

Sistemi kapatmak ve aynı anda tüm değişiklikleri yapmak çok riskli olabilir. Bir şeyler ters giderse ve sık sık yaparsa, geri dönüşün kolay bir yolu yoktur.

Çevik bir geliştirici olarak, bazen bu tablolar değiştirilip okunduğundan, herhangi bir kesinti olmadan tabloları yeniden gözden geçirmem gerekebilir.

Aşağıdaki yaklaşımın riski düşüktür, çünkü değişiklik, geri dönüşü çok kolay olan birkaç düşük riskli adımda yapılır:

  • Tabloya erişen tüm modüllerin otomatik testlerle iyi bir şekilde kaplandığından emin olun.
  • Yeni bir tablo oluşturun. Eski tabloyu değiştiren tüm prosedürleri değiştirin, böylece hem eski hem de yeni tabloları değiştirirler.
  • Var olan verileri yeni yapıya taşıyın. Ufacık gruplar halinde yapın, böylece sunucudaki genel performansı ciddi şekilde etkilemez.
  • Veri taşıma işleminin başarılı olduğunu doğrulayın.
  • Seçme prosedürlerinden bazılarını eski tablodan yenisine yönlendirin. Değiştirilen modüllerin hala doğru olduğundan emin olmak için otomatik testler kullanın. Performanslarının kabul edilebilir olduğundan emin olun. Değiştirilen prosedürleri dağıtın.
  • Tüm raporlar yeni tabloyu kullanana kadar önceki adımı tekrarlayın.
  • Tabloları değiştiren prosedürleri değiştirin, böylece yalnızca yeni tabloya erişirler.
  • Eski masayı arşivle ve sistemden çıkar.

Bu yaklaşımı büyük canlı üretim tablolarını kesinti olmadan, hiç sorun yaşamadan değiştirmek için birçok kez kullandık.


3
harika ... ama bu tam olarak kaçınmak istediğim bir "acı" türüdür :)
NeuronQ

@NeuronQ "Geri dönüşün kolay bir yolu yok " - Postgres'te var: basitçe her şeyi bir işleme koyun ve rollbackeğer bir şeyler ters giderse.
a_horse_with_no_name

2

Evet, birçok modern veri tabanı, bir sütunu eklemenize ya da bir sütunun özelliklerini değiştirmenize izin verir;

Bir sütunu düşürürseniz, veriler kaybedilecek, ancak çok fazla yolsuzluk korkusu yok.



-1

Bir ALTER TABLEifadeyle ne olacağı sorusunu ele almak, değişikliklerin kapsamına bağlıdır. Belirli durumlarda, en azından MS SQL Server'da yeni bir sütun eklerseniz, motor yeni tablo tanımını oluştururken tablonun geçici bir kopyasını oluşturur ve sonra verileri buraya ekler. Değişiklik süresince, tablo kullanıcılara erişilemez olacaktır.

MSSQL sunucusu için belirli işlemlere bir örnek burada verilmiştir: http://support.microsoft.com/kb/956176/tr

Diğer RMDB'lerin benzer yöntemlere sahip olduğunu varsayarım, ancak tam olarak uygulanması satıcı belgelerinde doğrulamak zorunda kalacağınız bir şey olabilir.


-1 Bu, SQL Server için tamamen yanlıştır: "En azından MS SQL Server'da yeni bir sütun eklerseniz, motor tablonun geçici bir kopyasını oluşturacak ve yeni tablo tanımını oluşturacak ve ardından verileri geri ekleyecektir. orada "
AK

@AlexKuznetsov - Yukarıdaki satırın, listelenen vakaların bazılarının bağlantısının her zaman gerçekleşmeyeceğini açıklığa kavuşturacağını düşündüm. Bunu daha iyi yansıtması için cümleyi değiştirdim.
SchmitzIT

1
SQL Server'ın davranışını değil, GUI'nin, SSMS'nin davranışından bahsediyorsunuz. Bağlantınızı izleyerek tavsiye, DDL değişikliklerini yapmak için doğrudan T-SQL kullanmaktır. SSMS, DDL'yi değiştirmek için çok iyi bir araç değildir.
AK

@AlexKuznetsov - Makaleyi, içerdiği risklerin olduğunu ama bir caydırıcılık olmadığını söyleyerek okudum. Her neyse, GUI biti için makaleyi bağlamadım, ancak altta yatan veri yapısındaki değişikliklerden dolayı geçici bir tablonun oluşturulmasına yol açan bir ALTER ifadesine yol açan bazı işlemlerin bir göstergesi olarak. İfadeyi doğrudan T-SQL'den verirken aynı şeyin geçerli olup olmadığını test etmedim, ancak işlemin oldukça benzer olduğunu ve SL Sunucusunun sahnelerin arkasındaki açıklamayı yaptığını düşünürdüm.
SchmitzIT

Profiler'ı başlatabilir, doğrudan ALTER TABLE ifadesini çalıştırabilir ve neler olduğunu görebilirsiniz. Ardından bir tabloyu bir iletişim kutusu aracılığıyla değiştirebilir ve yürütülen komutları kendiniz görebilirsiniz.
AK,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.