Büyük bir veritabanındaki bir mysqldump'u nasıl optimize edebilirim?


173

Ben 57 tabloları ile ~ 2GB olan bir InnoDB veritabanı ile bir symfony uygulama var. Veritabanının büyüklüğünün büyük bir kısmı tek bir tabloda (~ 1.2GB) bulunur. Şu anda veritabanını her gece yedeklemek için mysqldump kullanıyorum.

Comcast bağlantım nedeniyle, çoğu zaman bir dökümü manuel olarak çalıştırıyorsam, sunucuya olan bağlantım dökümü tamamlamadan önce zaman aşımına uğrayacak. [Şu anda her gece dökümü yapan bir cron çalıştırıyorum, bu sadece manuel olarak çalıştırdığım dökümler için.]

Bağlantı zaman aşımı sorununa ilişkin dökümleri hızlandırmanın yanı sıra, sunucunun bu işlemle meşgul olduğu süreyi sınırlandırmanın bir yolu var mı?

BTW, şu anda bu sorunu çözmek için toplam veritabanının boyutunu azaltmaya çalışıyorum.


2
Hangi parametreleri (varsa) mysqldump komutuna geçiyorsunuz?
Toby

--Compact eklemek sizin için bir seçenek olabilir.
Toby

gerçekten bir şey yok -mysqldump [database] -u[user] -p'[password]' > db_backup.sql
Patrick

4
screenDurumunuz için basit bir alternatif kullanmak nohup, bağlantınız kopsa bile komutunuzun sunucuda çalışmaya devam etmesine izin verecektir. Örn nohup mysqldump [options] > backup.sql 2> backup.err &. İçin bir çıktı dosyası sağlamazsanız nohup, nohup.outvarsayılan olarak oluşturur.
dabest1

1
Çok uzun bir boşta bağlantıdan sonra sizi susturan güvenlik duvarı ile ilgilenmenin yolları için atve screen(varsa sonuncular, ancak attüm unix'lerde standarttır) veya ServerAliveIntervalSSH seçeneklerine bir göz atın .
MattBianco

Yanıtlar:


134

Bu çöplükteki ana tıkanıklık, I / O sürücüsüdür. Bir veri yükünü okuyorsunuz ve tekrar yazıyorsunuz. Bunu birkaç şekilde hızlandırabilirsiniz:

  • Çıktınızın, veritabanı dosyalarının depolandığı sürücülerden farklı bir sürücüye / sürücülere gittiğinden emin olun - bu, sürücü kafaları sürekli okunmakta olan konum arasında titremeyeceğinden dönen disklerle büyük bir fark yaratacaktır. ve yazıldığı yer.
  • MySQLDump çıktısı çok sıkıştırılabilir olacaktır, bu nedenle çıktıyı yukarıda belirtilen girdilerden ayrı tutamazsanız, çıktı boyunca gzipveya benzer şekilde çıktı alın . Bu, bazı CPU zamanları pahasına (bu zamanlarda çok fazla boş zamanınız olabilir), yapılan yazı miktarını azaltacaktır (bu nedenle, genel IO yükünü ve kafa hareketi miktarını azaltın).
  • Ayrıca, (ayrıca veya sıkıştırma yerine) çıktıyı , sürücü hareketine daha fazla birlikte yazılan blokları gruplamak için büyük yazma tamponlarını destekleyen bir pv aracı ( pv gibi ) içinden geçirir , bu da baş hareketi gecikmesinin etkisini azaltır - --quickbüyük masaları yedeklemenin RAM etkisini azaltma seçeneğini kullanıyorsanız oldukça fark var ).
  • Yedekleme işleminizi yalnızca G / Ç yükü düşükse çalıştırın.

Yine de yanlış sorunu düzeltiyor olabilirsiniz: bunun yerine bağlantı kopmalarını ele almanız daha kolay olabilir (yedeklemelerinizin dayattığı G / Ç yükünü azaltmak, diğer kullanıcılar üzerindeki etkinizi azaltmaya yardımcı olacaktır, bu nedenle yine de denemeye değer). Manuel yedeklemelerinizi ekrandan (veya tmux gibi benzeri araçlar ) geçirebilir misiniz? Bu şekilde, sunucuyla bağlantınız koparsa, screenherhangi bir işlem kesintiye uğramadan tekrar bağlanıp oturuma yeniden bağlanabilirsiniz.

Verileri doğrudan bağlantı üzerinden gönderiyorsanız (yani, yerel makinenizde uzak bir veritabanına karşı mysqldump çalıştırıyorsunuz, bu nedenle döküm yerel olarak görünüyor), dökümü ilk önce sunucuda çalıştırıp gerektiğinde sıkıştırarak ve ardından aktarmadan daha iyi olabilirsiniz. Ağ üzerinden veri rsync, kısmi aktarımları destekleyen bir araç (örneğin ) kullanarak bağlantıyı kesmesi durumunda aktarımı devam ettirebilirsiniz (yeniden başlatma yerine).

“Bu sorunu çözmek için genel veritabanının boyutunu küçültmek” kapsamında, verilerinizin büyük bir kısmının değişmediğini tahmin ediyorum. 1.2Gb'lik büyük bir bölümü bu ana tablodan bir başkasına taşıyabilir ve mysqldumpçağrı tarafından kopyalananlardan kaldırabilirsiniz . Asla değişmezse, her zaman bu verileri yedeklemenize gerek yoktur. Verileri tablolar ve veritabanları arasında bu şekilde bölmek genellikle veri bölümlemesi olarak adlandırılır ve ayrıca verileri ve G / Ç yükünü birden fazla sürücüye yaymanıza izin verebilir. High-end veritabanı otomatik bölümlendirme desteği sağlamıştır, ancak mysql'de muhtemelen elle yapmanız ve veri erişim katmanınızı hesaba katmanız gerekecek.

Bu site için konu dışı kalmak (bu nedenle daha fazla ayrıntıya ihtiyacınız olup olmadığını sormak için muhtemelen ServerFault veya SuperUser'a bağlamanız gerekir): Hareketsizlik nedeniyle bağlantılarını kaybediyor gibi görünüyorsanız, SSH sunucunuzdaki ve SSH istemcinizdeki seçenekleri işaretleyin. Canlı tutma paketlerinin etkin olduğundan ve yeterince sık gönderildiğinden emin olun. Bağlantı etkin olsa bile bırakma görürseniz, OpenVPN veya bağlantıyı sarmaya benzer şekilde kullanmayı da deneyebilirsiniz - bağlantınızın tamamı birkaç saniye boyunca kapalı kalsa bile SSH istemcisi ve sunucu farketmez.


Sunucularıma yapılan ssh bağlantılarının sayısını azaltabilmeyi isterdim. Terminali ~ 60 saniyeden daha uzun süre kullanmayacaksam top, bağlantının düşmemesini sağlamak için koşarım . (İşyerinde yalnızca standart bir WRT yönlendirici ve güvenlik duvarı kullandığımızdan ve evdeki comcast bağlantım hiç bir zaman düşmediğinden dolayı, bu comcast bağlantısı olduğundan eminim)
Patrick

SSH bağlantılarına özel kısa bir not ekledim.
David Spillett

2
Bu cevabın derinliği ve içgörüsü. Bunun için +3 almalısın. Üzgünüm, sadece + 1 verebilirim.
RolandoMySQLDBA

116

Mysqldump İLE YEDEKLEME YAPMAYA INSIGHT

IMHO Sadece nasıl yaklaşacağınızı biliyorsanız, yedekleme yapmak bir sanat formuna dönüşmüştür.

Seçeneklerin var

Seçenek 1: mysqldump bir mysql örneği

Bu en kolay olanı, no-brainer !!!

mysqldump -h... -u... -p... --hex-blob --routines --triggers --all-databases | gzip > MySQLData.sql.gz

Tek bir dosyada yazılmış her şey: tablo yapıları, indeksler, tetikleyiciler, saklı prosedürler, kullanıcılar, şifreli şifreler. Diğer mysqldump seçenekleri, farklı INSERT komut stillerini, günlük dosyasını ve konum koordinatlarını ikili günlüklerden, veritabanı oluşturma seçeneklerinden, kısmi veriden (- yerden seçeneği) vb. Dışa aktarabilir.

Seçenek 2: mysqldump ayrı veritabanlarına ayrı veri dosyalarına

Bir veritabanı listesi oluşturarak başlayın (bunu yapmak için 2 teknik)

Teknik 1

mysql -h... -u... -p... -A --skip-column-names -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Teknik 2

mysql -h... -u... -p... -A --skip-column-names -e"SELECT DISTINCT table_schema FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Teknik 1 en hızlı yoldur. Teknik 2 en kesin ve en güvenli olandır. Teknik 2 daha iyidir, çünkü bazen kullanıcılar / var / lib / mysql (datadir) 'de genel amaçlı, veritabanı ile ilgili olmayan klasörler oluştururlar. İnformation_schema, klasörü information_schema.schemata tablosuna bir veritabanı olarak kaydeder. Teknik 2, mysql verisi içermeyen klasörleri atlar.

Veritabanlarının listesini derledikten sonra, listede dolaşmaya devam edebilir ve istenirse paralel olarak bile mysqldump atabilirsiniz.

for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
done
wait

Bir seferde başlatılacak çok fazla veritabanı varsa, paralel olarak bir seferde 10'a boşaltın:

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Seçenek 3: mysqldump ayrı tabloları ayrı veri dosyalarına

Bir tablo listesi oluşturarak başlayın

mysql -h... -u... -p... -A --skip-column-names -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfTables.txt

Sonra tüm tabloları 10'lu gruplar halinde boşalt

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DBTB in `cat ListOfTables.txt`
do
    DB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $2}'`
    mysqldump -h... -u... -p... --hex-blob --triggers ${DB} ${TB} | gzip > ${DB}_${TB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Seçenek 4: GÖRÜNTÜLEĞİNİZİ KULLANIN

Yukarıda belirtilen Seçeneklerin varyasyonlarını ve temiz fotoğraflar için teknikleri deneyin

Örnekler

  1. Tablo listesini, artan veya azalan tabloların boyutuna göre sıralayın.
  2. Ayrı bir işlem kullanarak, mysqldumps'ı başlatmadan önce "HIZLI TABLOLARI OKUYAN KİLİTLE; UYKU SEÇİMİ (86400)" çalıştırın. MyShldumps tamamlandıktan sonra bu işlemi öldür. Bir veritabanı hem InnoDB hem de MyISAM içeriyorsa bu yararlıdır.
  3. Mysqldumps tarihli klasörlere kaydedin ve eski yedek klasörleri dışarı döndürün.
  4. Tüm örnek mysqldumps bağımsız sunuculara yükleyin.

UYARI

Sadece Seçenek 1 her şeyi getirir. Dezavantajı, bu şekilde oluşturulan mysqldumps'ın, mysqldump'un oluşturduğu mysql'nin yalnızca aynı sürüm sürümüne yeniden yüklenebilmesidir. Başka bir deyişle, bir MySQL 5.0 veritabanından bir mysqldump, 5.1 veya 5.5'e yüklenemez. Sebep ? MySQL şeması büyük sürümleri arasında tamamen farklıdır.

Seçenek 2 ve 3, kullanıcı adlarını ve şifreleri kaydetmeyi içermez.

İşte daha okunaklı ve daha taşınabilir kullanıcılar için SQL Grants'tan kurtulmanın genel yolu

mysql -h... -u... -p... --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql -h... -u... -p... --skip-column-names -A | sed 's/$/;/g' > MySQLGrants.sql

Seçenek 3 saklı yordamları kaydetmediğinden, aşağıdakileri yapabilirsiniz

mysqldump -h... -u... -p... --no-data --no-create-info --routines > MySQLStoredProcedures.sql &

Dikkat edilmesi gereken bir diğer nokta, InnoDB ile ilgilidir. Büyük bir InnoDB tampon havuzunuz varsa, herhangi bir yedekleme yapmadan önce onu en iyi şekilde yıkamak mantıklıdır. Aksi takdirde, MySQL zaman yıkama tablolarını artık kirli sayfalarla arabellek havuzunun dışına harcar. İşte önerdiğim şey:

Yedeklemeyi gerçekleştirmeden yaklaşık 1 saat önce bu SQL komutunu çalıştırın

SET GLOBAL innodb_max_dirty_pages_pct = 0;

MySQL 5.5'te varsayılan innodb_max_dirty_pages_pct 75'tir. MySQL 5.1 ve arkasında, varsayılan innodb_max_dirty_pages_pct 90'dır. İnnodb_max_dirty_pages_pct değerini 0 olarak ayarlayarak bu, kirli sayfaların diske temizlenmesini hızlandıracaktır. Bu, herhangi bir InnoDB tablosuna karşı herhangi bir mysqldump yapmadan önce, InnoDB verilerinin eksik olan iki fazlı işlemlerini temizleme etkisini önleyecek veya en azından azaltacaktır.

Mysqldump üzerinde son dünya

Çoğu insan mysqldump’tan diğer araçların lehine uzak durmaktadır ve bu araçlar gerçekten iyidir.

Bu araçlar arasında

  1. MAATKIT (paralel boşaltma / geri yükleme komut dosyaları, Percona'dan [Deprecated but great])
  2. XtraBackup ( Percona'dan TopNotch Anlık Görüntüsü Yedeklemesi)
  3. CDP R1Soft ( Zamanında anlık görüntüler alan MySQL Modül Seçeneği )
  4. MySQL Kurumsal Yedekleme (eski adıyla InnoDB Hot Backups [ticari])

Gerçek bir MySQL DBA ruhuna sahipseniz, mysqldump'ı kucaklayabilir ve üzerinde tam bir ustalığa sahip olabilirsiniz. Tüm yedeklemeleriniz MySQL DBA becerilerinizin bir yansıması olabilir .


2
Hem mysqldump'un hem de iyi kullanımı için +1: Gerçek bir MySQL DBA ruhuna sahipseniz, mysqldump'ı kucaklayabilir ve üzerinde tam bir ustalığa sahip olabilirsiniz. Tüm yedeklemeleriniz MySQL DBA olarak yeteneklerinizin bir yansıması olabilir .... Harika çizgiler !!!
Abdul Manaf

4
InnoDB’de tabloları tek tek boşaltmak tutarsız bir yedekleme sağlar.
Alain Collins,

5
@AlainCollins bu nedenle mysqldumps'u yalnızca okunan bir çoğaltma kölesi üzerinde çalıştırıyorum. Seconds_Behind_Master 0 olduğunda, STOP SLAVE'ı çalıştırın. Şimdi, yukarıda belirtilen stillerden herhangi birinde mysqldumps yapmak için tutarlı bir noktaya sahipsiniz. Bunu, 5 yıldır online ticaret şirketleri için bana veya şirket sahiplerime tek bir şikayette bulunmaksızın yaptım. Bu andan itibaren, bu müşteri için her 10 dakikada bir paralel mysqldumps yapıyorum. Bunu diğer istemciler için daha hızlı yedekleme süreleri sağlaması için de yapıyorum.
RolandoMySQLDBA

32 GB db'im var, yani 3. seçenek tam olarak aklımdaki buydu! Teşekkürler!
Raymond

Çok büyük boyutlarda küçültmek için 1TB veriyi yedeklemeli ve yeniden almalıyım ibdata1. Donanım RAID destekli SSD'lerin zamanlarında seçenek 3 benim için tek çözüm.
Rabud

18

MySQL replikasyon master'ına köle olarak bakın. Master veritabanını aynı veritabanı ile başka bir veritabanı sunucusuna kopyalamanıza izin verir. Bu, ana ve köle kimliklerini içerir. Slave kendisini ana veritabanı sunucusunun ve / veya veritabanlarının tam kopyasını yapar. Efendi (ler) ve köle (ler) arasında bir, bir, çok, çok-bir ilişki olabilir.

Slave, master'daki ikili logu sürekli okur (bin log, master veritabanı sunucusunda yazılan sorguları saklar) ve slave veritabanı sunucusuna giriş yapar. (Bu, ana veritabanınızın hiç etkilenmeyeceği anlamına gelir)

İyi haber şu ki, MySQL sunucunuzu herhangi bir kesinti veya yavaş sorgu yanıtları farketmeyecek kadar fazla etkilemeyeceği. 10Gb veritabanları için kullanıyoruz ve herhangi bir kesinti olmadan bir cazibe gibi çalışıyor.

Aynı Makinede MySQL Çoğaltma


Bu benim için işe yarayacak iken, biraz overkill olabileceğini düşünüyorum. Şu anda bu yedekleme düzeyine ihtiyacım yok, ancak uygulamanın gereklilikleri değiştiğinde bunu aklımda tutacağım.
Patrick

4
Ana DB'den yedeklemenin GÇ yükünü kaldırmak için bir kopyayı yedeklemek için +1 ve önemli bir uyarı ile potansiyel kilitleme ile ilgili sorunları azaltın: "Aynı makinedeki kopyala" seçeneğine dikkat edin IO bant genişliği için master ile rekabet edebilir - bu sorunu gidermek için slave'in veri dosyalarının master'dan farklı bir sürücü / dizi olduğundan emin olun.
David Spillett

1
Ditto, David Splllet'in Yorumuna. Web Hosting İşverenim için köleler üzerinde mysqldump yedekleri olan düzinelerce Master / Slave kurdum ve bakımını yapıyorum. Benden de +1.
RolandoMySQLDBA

16

Plan A: Ayrıca bakınız Percona'dan Xtrabackup. Bu, önemli bir kilitleme olmadan InnoDB'nin çevrimiçi olarak yedeklenmesini sağlar.

B Planı: Bir Slave durdurulabilir ve çeşitli yollardan biriyle (kopya dosyaları, mysqldump, xtrabackup, vb.) Tutarlı bir yedekleme alabilirsiniz.

Plan C: LVM Anlık Görüntüsü. Bazı şifreli kurulumdan sonra, bir yedeklemenin durma süresi, veritabanının boyutuna bakılmaksızın bir dakikadan daha azdır. MySQL'i durdurun, anlık görüntüyü yapın, mysqld'i yeniden başlatın, sonra anlık görüntüyü kopyalayın. Son adım uzun zaman alabilir, ancak MySQL kapalı değil.

Plan D: Bir Kölenin Anlık Görüntüsü - sıfır kesinti süresi.


2
Hoorah dört planın hepsine. Cevap başına sadece +0.25 verebilirim !!! +1 (4 x 0,25)
RolandoMySQLDBA

15

İlk önce birkaç yönetici noktası: Bir ftp yapmak için mi bağlanıyorsunuz, yoksa ssh'ed misiniz ve ölüyor mu? Ssh ise, comcast çökmesinden sonra devam edebilmeniz için ekranı kullandığınızdan emin olun . Ftp ise, göndermeden önce / tar sıkıştırdığınızdan emin olun.

Ayrıca --opt parametresini veya --quick'i deneyin.

--opt Bu seçenek, boşaltma ve yeniden yükleme işlemlerini daha verimli hale getirmek için bir dizi ek seçeneği açar. Özellikle, --add-drop-table, --add-lock, --all, --quick, --extended-insert, --lock-table ve --disable-key seçeneklerini birlikte kullanmakla eşdeğerdir. Bu seçeneğin çıktıyı daha az taşınabilir hale getirdiğini ve diğer veritabanı sistemleri tarafından anlaşılma olasılığını azalttığını unutmayın.

--quick Bu seçenek, mysqldump'a sunucudan her satır okurken, büyük tablolar için yararlı olabilecek döküm çıktısı yazmalarını söyler. Varsayılan olarak, mysqldump çıktıyı yazmadan önce bir tablodaki tüm satırları belleğe okur; Büyük tablolar için bu, büyük olasılıkla çöplüğün başarısız olmasına neden olan büyük miktarda bellek gerektirir.


1
--Opt, sonunda çıktısını alacak dosyanın boyutunu arttırmaz mı?
Toby

Bazılarını ekleyecektir - eklemek istedim - sorusuna daha fazla cevap veren - çabuk… şimdi düzenleme. Teşekkürler!
David Hall,

Bu sorunu tamamen önleyen ekran için +1
Gaius

Mysqldump's --opt ve --quick açıklamalarına çok güzel ve özlü bir cevap için +1.
RolandoMySQLDBA

1
--opt varsayılan olarak açıktır.
Jordan

5

Büyük veritabanlarının dökümü sırasında zaman aşımları ile ilgili sorunlarım vardı. Db'deki her tablo için ayrı komutlar göndererek ve bunun gibi bir dosyaya her şeyi ekleyerek son olarak çözdüm:

TABLES=`mysql -u $USER -p$PWD -Bse 'show tables' $DB`
for TABLE in $TABLES
do
    mysqldump -u $USER -p$PWD $DB $TABLE >> dump.sql
done

4
Bu "tutarsız" bir yedekleme olarak kabul edilir, çünkü geri yüklendikten sonra bir tabloda diğerine eşlenen ancak var olmayan veriler olabilir.
Morgan Tocker,

3

Bence sorunun farklı bir yedekleme çözümü değil, mysqldump'un oluşturduğu döküm dosyalarından nasıl daha hızlı geri yükleneceği ile ilgili olduğunu düşünüyorum.

Bunu yapmanın yollarından biri, şemanızda tablo grupları oluşturarak ve her grup için ayrı bir DB kullanıcısı oluşturarak, daha sonra son olarak MySQL izinlerini kullanarak tabloların yalnızca bir DB kullanıcısını kullanmaya eklenmesine izin vermeyecek şekilde kullanmaktır.

Bu kanıtlanmış, hızlı, neredeyse paralel bir tekniktir ancak% 100 emin değil, 500 G gibi büyük çöplüklerden geri yükleme ne kadar sürecek. Ama benim düşünceme göre bence paralel bir şeye ihtiyacın var. Örnek için aşağıdaki bağlantıyı kontrol edin.

[MySQL için SQL dökümlerinden (mysqldump) hızlı, paralel geri yükleme] [1]

http://geeksww.com/tutorials/database_management_systems/mysql/tips_and_tricks/fast_parallel_restore_from_sql_dumps_mysqldump_for_mysql.php

"MySQL için SQL dökümlerinden (mysqldump) hızlı, paralel geri yükleme"


2
Bu, başka bir soruya verdiğiniz cevabın tam bir kopyasıdır . Bu özel soru için biraz daha özelleştirmek isteyebilirsiniz.
Paul Beyaz

Soru özellikle daha hızlı geri yükleme ile ilgili DEĞİLDİR.
andrew lorien
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.