Nasıl 66.862.521 satır tablo MyISAM birkaç saat için çevrimdışı olmadan InnoDB dönüştürmek için?


18

büyük bir MyISAM tablosunu uygulamayı çevrimdışına almadan InnoDB'ye dönüştürmek mümkün (ve nasıl)? Bu tabloya her saniye birkaç satır eklemek gerekir, ancak yaklaşık 2 dakika boyunca askıya almak mümkündür.

Açıkça ALTER TABLE ... engine = innodb çalışmaz. Bunun için innodb motoruyla yeni bir tablo oluşturmayı ve içeriği ona kopyalamayı planladım. Ve sonunda, uygulama günlüğü iş parçacığını askıya alın ve tabloyu yeniden adlandırın.

Ne yazık ki, 100 satırlık küçük gruplar halinde kopyalama bile bir süre sonra önemli bir gecikme yaratır.

Düzenleme : Mevcut satırlar hiçbir zaman değiştirilmez, bu tablo günlük kaydı için kullanılır.



3
Bu soru konuşma süresini en aza indirmektir. Konuşmaların birkaç gün veya hafta sürdüğü umurumda değil. Ancak uygulamanın duruş süresi gerekmeksizin ve belirgin bir gecikme yaratmadan arka planda çalışmalıdır.
Hendrik Brummermann

Yanıtlar:


15

Aşağıdaki gibi bir Master-Master kurulumu oluşturun:

  • İkinci master oluşturun, MasterB
  • MasterB köle gibi davranır logTable
  • Oluştur logTable_newinnodb olarak
  • INSERT INTO logTable_new SELECT * FROM logTableÇoğaltmayı MasterA'ya gönderen MasterB'de (psuedocode) çalıştırın
  • logTable_newMasterA açıkken senkronizasyonu bitirdiğinde tabloları değiştirin

10

Aşağıdaki kısıtlamalar göz önüne alındığında:

Konuşmaların birkaç gün veya hafta sürdüğü umurumda değil. Ancak uygulamanın duruş süresi gerektirmeden ve fark edilir bir gecikme yaratmadan arka planda çalışmalıdır.

Günlük kaydı yaparken, bir işaretleyici ayarlamak için iyi bir yolunuz varsa, böylece işleme ne başlattığınızı anlayabilirsiniz, böylece daha sonra günlükleri yeniden uygulayabilir veya günlüklerin bir metin dosyasına yazılmasını sağlayabilirsiniz. daha sonra onları yenebilirsin LOAD DATA INFILE

Sorunun bir kısmı, daha küçük gruplar halinde yazmanın, dizinlerin tekrar tekrar hesaplanması gerektiği anlamına gelmesidir; hepsini bir kerede çalıştırmak daha iyi, ancak bu sistemde bazı 'fark edilebilir' gecikmeye neden olabilir .. ama bunu üretim sunucunuzda yapmak zorunda değilsiniz.

  1. Günlüğü duraklatın veya daha sonra bu noktadan günlükleri yeniden uygulayabilmeniz için bir işaretleyici ayarlayın.
  2. MyISM tablonuzu başka bir sisteme kopyalayın
  3. Diğer sistemde, farklı bir ad altında bir InnoDB tablosu oluşturun ve verileri taşıyın (dökümü ve kullanımı daha da hızlı olabilir LOAD DATA INFILE)
  4. InnoDB tablosunu orijinal sisteme geri kopyalayın
  5. Günlük kaydı için başka bir işaretleyici ayarlayın.
  6. Son iki işaretçi arasındaki tüm günlükleri yeni tabloya yeniden uygulayın.
  7. (# 6 numaralı adım bir dakikadan daha uzun sürdüyse 5 ve 6 numaralı adımları tekrarlayın, yalnızca birkaç saniye olana kadar)
  8. Tabloları değiştirin (eskisini adının altındaki yenisini table_BACKUP olarak yeniden adlandırın)
  9. Son işaretleyiciden beri günlükleri yakalayın.

9

Ne yazık ki, 100 satırlık küçük gruplar halinde kopyalama bile bir süre sonra önemli bir gecikme yaratır.

Her toplu iş arasında herhangi bir gecikme ekliyor musunuz, yoksa yalnızca güncellemeleri topluyor ve her toplu işi bir öncekinden hemen sonra mı çalıştırıyorsunuz?

Öyleyse, dönüşümü en sevdiğiniz dilde aşağıdaki gibi bir komut dosyası oluşturmayı deneyin:

repeat
    copy oldest 100 rows that haven't been copied yet to new table
    sleep for as long as that update took
until there are <100 rows unprocessed
stop logging service
move the last few rows
rename tables
restart logging
delete the old table when you are sure the conversion has worked

Bu, dönüşümün, sistemin kullanımı zamana göre değiştiği için uygulanan yük farklılıklarına izin vermesine rağmen sunucunuzun kapasitesinin yarısından fazlasını almamasını sağlamalıdır.

Eğer veritabanı ihtiyacı olan kullanıcılar için bazı işler yapmak zaman hizmet nispeten boştayken mümkün olduğunca zaman olarak kullanabilir ama (potansiyel olarak zaman oldukça uzunluk için duraklatma) geri çekilmesini istiyorsanız Veya, yerini sleep for as long as the update tookile if the server's load is above <upper measure>, sleep for some seconds then check again, loop around the sleep/check until the load drops below <lower measure>. Bu, sessiz zamanlarda ilerleyebileceği anlamına gelir, ancak sunucu normal iş yükünü gerçekleştirmekle meşgul olduğunda tamamen duraklar. Yükün belirlenmesi işletim sisteminize bağlı olacaktır - Linux altında ve buna benzer 1 dakikalık yük ortalama değeri /proc/loadavgveya çıkışının yapılması uptimegerekir. <lower measure>ve <upper measure>aynı değer olabilir, ancak bunun gibi kontrollerde bir fark olması olağandır, bu nedenle işleminiz başlamaya devam etmez ve yük ölçümü üzerinde etkisi olan kendi yeniden başlatması nedeniyle hemen duraklamaz.

Tabii ki bu, eski satırların değiştirilebileceği tablolar için işe yaramaz, ancak tanımladığınız gibi bir günlük tablosu için iyi çalışır.

Bu durumda yeni tabloyu doldurduktan sonra dizin oluşturma bilgeliğini göz ardı etmek isteyeceksiniz . İşlerin olabildiğince hızlı olmasını istediğinizde bu gerçekten daha verimli olsa da (sistemin geri kalanı üzerindeki etki lanetlenir), bu durumda işlemin sonunda büyük yük bolluğunu istemezsiniz. dizinler tek seferde tamamen oluşturulur, çünkü işler meşgul olduğunda duraklayamayacağınız bir işlemdir.


4

Bunun gibi bir şey olur mu?

  1. Günlüğü duraklat (böylece $auto_incrementgünlük tablonuzdakimytable değişmez).
  2. $auto_incrementKullanarak değeri not edin SHOW TABLE STATUS LIKE 'mytable'.
  3. CREATE TABLE mytable_new LIKE mytable
  4. ALTER TABLE mytable_new AUTO_INCREMENT=$auto_increment ENGINE=Innodb
  5. RENAME TABLE mytable TO mytable_old, mytable_new TO mytable
  6. Günlüğe kaydetmeyi yeniden etkinleştirin. Innodb tablosu şimdi doldurmaya başlayacaktır.
  7. INSERT INTO mytable SELECT * FROM mytable_old.

Normal günlük kaydını engellememesi gerektiğinden 7. adımı toplu olarak veya tek bir deyimle yapabilirsiniz.


innodb'un auto_increment'i işleme biçimi nedeniyle hala engelleme yapıyor olacaktı. varsayılan olarak innodb, auto_increment sütununa eklerken tablo düzeyinde bir kilit alır ve ekleme tamamlanır tamamlanmaz kilidi serbest bırakır.
ovais.tariq
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.