it-swarm.asia

كيف يمكنني تحسين mysqldump لقاعدة بيانات كبيرة؟

لدي تطبيق symfony مع قاعدة بيانات InnoDB التي تبلغ ~ 2 جيجابايت مع 57 جدولًا. تكمن غالبية حجم قاعدة البيانات في جدول واحد (~ 1.2GB). أستخدم حاليا mysqldump لعمل نسخة احتياطية من قاعدة البيانات كل ليلة.

نظرًا لاتصال Comcast الخاص بي ، غالبًا ما إذا قمت بتشغيل ملف تفريغ يدويًا ، فإن مهلة الاتصال بالخادم ستنتهي قبل اكتمال التفريغ مما يؤدي إلى إعادة تشغيل التفريغ. [أقوم حاليًا بتشغيل أحد الأشخاص الذين يقومون بعملية التفريغ كل ليلة ، وهذا لمجرد عمليات التفريغ التي يتم تشغيلها يدويًا.]

هل هناك طريقة لتسريع تفريغ مشكلة مهلة الاتصال ، ولكن أيضًا للحد من الوقت الذي يشغل فيه الخادم بهذه العملية؟

راجع للشغل ، أنا أعمل حاليًا على تقليل حجم قاعدة البيانات الإجمالية لحل هذه المشكلة.

179
Patrick

الاختناق الرئيسي في التفريغ مثل محرك الأقراص I/O. أنت تقرأ كمية كبيرة من البيانات وتكتبها مرة أخرى. يمكنك تسريع ذلك بعدة طرق:

  • تأكد من أن مخرجاتك ستنتقل إلى محرك (محركات) أقراص مختلف عن محرك (محركات) ملفات قاعدة البيانات المخزنة عليه - وهذا سيحدث فرقًا كبيرًا مع الأقراص الدوارة حيث لن تتحرك رؤوس محركات الأقراص باستمرار بين الموقع الذي تتم قراءته من والموقع الذي تتم الكتابة إليه.
  • سيكون ناتج mysqldump قابلاً للانضغاط جدًا ، لذلك إذا لم تتمكن من فصل الإخراج عن الإدخال كما هو مذكور أعلاه ، فإن الإخراج من خلال gzip أو ما شابه. سيؤدي هذا إلى تقليل كمية الكتابة التي يتم إجراؤها (لذا قلل إجمالي IO ، ومقدار حركة الرأس) على حساب بعض وقت وحدة المعالجة المركزية (التي قد يكون لديك الكثير من الوقت في هذه الأوقات على أي حال).
  • أيضًا ، (أيضًا أو بدلاً من الضغط) قم بتمرير الإخراج من خلال أداة الأنابيب (مثل pv ) التي تدعم مخازن الكتابة الكبيرة لتجميع الكتل المكتوبة على محركات الأقراص معًا أكثر ، مرة أخرى لتقليل تأثير الرأس - وقت الانتقال - سيحدث هذا فرقًا كبيرًا في حالة استخدام --quick الخيار لتقليل RAM تأثير النسخ الاحتياطي للجداول الكبيرة).
  • قم بتشغيل عملية النسخ الاحتياطي فقط عندما يكون تحميل IO منخفضًا بخلاف ذلك.

ربما تكون قد أصلحت المشكلة الخاطئة على الرغم من ذلك: قد يكون من الأسهل معالجة انقطاع الاتصال بدلاً من ذلك (على الرغم من أن تقليل حمل الإدخال/الإخراج الذي تفرضه النسخ الاحتياطية سيساعد على تقليل التأثير الذي لديك على المستخدمين الآخرين ، لذا يجدر المحاولة على أي حال). هل يمكنك تشغيل النسخ الاحتياطية اليدوية من خلال شاشة (أو أدوات مماثلة مثل tmux )؟ بهذه الطريقة إذا انقطع اتصالك بالخادم ، يمكنك فقط إعادة الاتصال بالجلسة screen وإعادة توصيلها دون مقاطعة أي عمليات.

إذا كنت ترسل البيانات مباشرة عبر الاتصال (أي أنك تقوم بتشغيل mysqldump على جهازك المحلي مقابل قاعدة بيانات بعيدة ، لذلك يظهر التفريغ محليًا) ، فقد يكون من الأفضل تشغيل التفريغ على الخادم أولاً ، والضغط حسب الحاجة ، ثم نقل البيانات عبر الشبكة باستخدام أداة (مثل rsync) تدعم عمليات النقل الجزئية حتى تتمكن من استئناف النقل (بدلاً من إعادة التشغيل) إذا كان انقطاع الاتصال يقاطعها.

كجزء من "تقليل حجم قاعدة البيانات الإجمالية لحل هذه المشكلة" ، أعتقد أن جزءًا كبيرًا من بياناتك لا يتغير. قد تتمكن من نقل جزء كبير من 1.2 جيجا بايت من تلك الطاولة الرئيسية إلى أخرى وإزالتها من تلك التي يتم نسخها بواسطة استدعاء mysqldump. لا تحتاج إلى نسخ هذه البيانات احتياطيًا في كل مرة إذا لم تتغير أبدًا. عادةً ما يُشار إلى تقسيم البيانات بين الجداول وقواعد البيانات بهذه الطريقة على أنها تقسيم البيانات ويمكن أن يسمح لك أيضًا بتوزيع البيانات وتحميل الإدخال/الإخراج على محركات أقراص متعددة. تم بناء قاعدة البيانات المتطورة لدعم التقسيم التلقائي ، على الرغم من أنه في mysql قد تضطر إلى القيام بذلك يدويًا وتغيير طبقة الوصول إلى البيانات الخاصة بك لحسابها.

الابتعاد عن الموضوع لهذا الموقع (لذا يجب عليك على الأرجح الانتقال إلى ServerFault أو SuperUser للسؤال عما إذا كنت بحاجة إلى مزيد من التفاصيل): إذا كنت يبدو أنك تفقد الاتصالات بسبب عدم النشاط ، تحقق من الخيارات في خادم SSH وعميل SSH لإجراء تأكد من تمكين الحزم استمرار وإرسالها في كثير من الأحيان بما فيه الكفاية. إذا رأيت قطرات حتى إذا كان الاتصال نشطًا ، فيمكنك أيضًا تجربة استخدام OpenVPN أو ما شابه لف الاتصال - يجب أن يعالج انخفاضًا قصيرًا ، أو حتى انخفاضًا كاملاً إذا كان الاتصال بأكمله معطلاً لبضع ثوان ، مثل عميل SSH و الخادم لا يلاحظ.

139
David Spillett

نظرة ثاقبة للقيام بعمل نسخ احتياطية مع mysqldump

أصبح إجراء النسخ الاحتياطية IMHO أكثر من شكل فني إذا كنت تعرف فقط كيفية التعامل معها

لديك خيارات

الخيار 1: mysqldump نسخة كاملة من mysql

هذا هو الأسهل ، بلا تفكير !!!

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

كل شيء مكتوب في ملف واحد: هياكل الجدول ، الفهارس ، المشغلات ، الإجراءات المخزنة ، المستخدمون ، كلمات المرور المشفرة. يمكن أيضًا لخيارات mysqldump الأخرى تصدير أنماط مختلفة من أوامر INSERT وملف السجل وإحداثيات الموضع من السجلات الثنائية وخيارات إنشاء قاعدة البيانات والبيانات الجزئية (خيار أين) وما إلى ذلك.

الخيار 2: قواعد بيانات منفصلة mysqldump في ملفات بيانات منفصلة

ابدأ بإنشاء قائمة قواعد البيانات (طريقتان للقيام بذلك)

التقنية 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

التقنية 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

التقنية 1 هي أسرع طريقة. التقنية 2 هي الأكثر أمانا. التقنية 2 أفضل لأنه في بعض الأحيان ، ينشئ المستخدمون مجلدات لأغراض عامة في/var/lib/mysql (datadir) لا تتعلق بقاعدة البيانات. ستقوم information_schema بتسجيل المجلد كقاعدة بيانات في جدول information_schema.schemata. ستتجاوز التقنية 2 المجلدات التي لا تحتوي على بيانات الخلية.

بمجرد تجميع قائمة قواعد البيانات ، يمكنك المتابعة للتكرار من خلال القائمة و mysqldump عليها ، حتى بالتوازي إذا رغبت في ذلك.

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

إذا كان هناك عدد كبير جدًا من قواعد البيانات ليتم تشغيلها في وقت واحد ، فقم بتفريغها بشكل متوازٍ 10:

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

الخيار 3: mysqldump جداول منفصلة في ملفات بيانات منفصلة

ابدأ بإنشاء قائمة بالجداول

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

ثم تفريغ جميع الجداول في مجموعات من 10

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

الخيار 4: استخدم خيالك

جرب أشكال مختلفة من الخيارات المذكورة أعلاه بالإضافة إلى تقنيات اللقطات النظيفة

أمثلة

  1. ترتيب قائمة الجداول حسب حجم كل جدول تصاعدي أو تنازلي.
  2. باستخدام عملية منفصلة ، قم بتشغيل "FLUSH TABLES WITH READ LOCK؛ SELECT SLEEP (86400)" قبل إطلاق mysqldumps. قتل هذه العملية بعد اكتمال الخلية. هذا مفيد إذا كانت قاعدة البيانات تحتوي على كل من InnoDB و MyISAM
  3. احفظ mysqldumps في مجلدات مؤرخة وقم بتدوير مجلدات النسخ الاحتياطي القديمة.
  4. تحميل mysqldumps مثيل كامل في خوادم قائمة بذاتها.

[~ # ~] تحذير [~ # ~]

فقط الخيار 1 يجلب كل شيء. العيب هو أن mysqldumps الذي تم إنشاؤه بهذه الطريقة لا يمكن إعادة تحميله إلا في نفس إصدار الإصدار الرئيسي من mysql الذي تم إنشاؤه لـ mysqldump. بمعنى آخر ، لا يمكن تحميل mysqldump من قاعدة بيانات MySQL 5.0 في 5.1 أو 5.5. السبب ؟ مخطط الخلية مختلف تمامًا بين الإصدارات الرئيسية.

لا يتضمن الخياران 2 و 3 حفظ أسماء المستخدمين وكلمات المرور.

فيما يلي الطريقة العامة لتفريغ SQL Grants للمستخدمين المقروءين والمحمولين أكثر

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

لا يحفظ الخيار 3 الإجراءات المخزنة ، لذا يمكنك القيام بما يلي

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

نقطة أخرى ينبغي ملاحظتها تتعلق InnoDB. إذا كان لديك تجمع مؤقت كبير في InnoDB ، فمن المنطقي أن تقوم بتنظيفه قدر الإمكان قبل إجراء أي نسخ احتياطية. خلاف ذلك ، يقضي MySQL الوقت في مسح الجداول مع الصفحة القذرة المتبقية من تجمع المخزن المؤقت. إليك ما أقترحه:

حوالي 1 ساعة قبل تنفيذ النسخ الاحتياطي ، قم بتشغيل أمر SQL هذا

SET GLOBAL innodb_max_dirty_pages_pct = 0;

في MySQL 5.5 الافتراضي innodb_max_dirty_pages_pct هو 75. في MySQL 5.1 والعكس ، فإن innodb_max_dirty_pages_pct هو 90. من خلال تعيين innodb_max_dirty_pages_pct على 0 ، سيؤدي ذلك إلى تسريع تدفق الصفحات المتسخة إلى القرص. سيؤدي ذلك إلى منع أو على الأقل تقليل تأثير تنظيف أي عمليات غير مكتملة على مرحلتين من بيانات InnoDB قبل إجراء أي mysqldump مقابل أي جداول InnoDB.

كلمة نهائية على mysqldump

يخجل معظم الناس من mysqldump لصالح أدوات أخرى وهذه الأدوات جيدة بالفعل.

وتشمل هذه الأدوات

  1. MAATKIT (متوازي تفريغ / استعادة نصوص من بيركونا [مهمل ولكن رائع])
  2. XtraBackup (نسخة احتياطية من لقطة TopNotch من بيركونا)
  3. CDP R1Soft ( خيار وحدة MySQL التي تأخذ لقطات في وقت معين)
  4. MySQL Enterprise Backup (سابقًا InnoDB Hot Backups [تجاري])

إذا كانت لديك روح MySQL DBA حقيقية ، يمكنك تبني mysqldump والحصول على إتقان كامل يمكن تحقيقه. قد تكون جميع النسخ الاحتياطية الخاصة بك انعكاسًا لمهاراتك باعتبارها MySQL DBA .

122
RolandoMySQLDBA

ألق نظرة على سيد النسخ المتماثل MySQL للعبد. يسمح لك باستنساخ قاعدة البيانات الرئيسية إلى خادم قاعدة بيانات آخر بنفس قاعدة البيانات. يتضمن هويات السيد والعبد. يجعل Slave نفسه نسخة طبق الأصل من خادم قاعدة البيانات الرئيسي و/أو قواعد بياناته. قد يكون هناك علاقة واحد ، واحد كثير ، واحد كثير بين سيد (ق) والعبيد (ق).

Slave يقرأ باستمرار السجل الثنائي في الصفحة الرئيسية (يخزن سجل bin الاستعلامات المكتوبة في خادم قاعدة البيانات الرئيسي) ويحصل على مدخلات إلى خادم قاعدة البيانات التابع. (هذا يعني أن قاعدة البيانات الرئيسية الخاصة بك لن تتأثر على الإطلاق)

الخبر السار هو أنه لن يؤثر على خادم MySQL الخاص بك كثيرًا كما في أنك لن تلاحظ أي أوقات تعطل أو استجابات بطيئة للاستعلام. نحن نستخدمها لقواعد بيانات 10Gb وهي تعمل مثل السحر دون أي توقف.

النسخ المتماثل MySQL على نفس الجهاز

20
poelinca

الخطة أ: انظر أيضًا Xtrabackup من بيركونا. وهذا يسمح بالنسخ الاحتياطي عبر الإنترنت لـ InnoDB ، دون أي قفل هام.

الخطة ب: يمكن إيقاف الرقيق ، ويمكنك أخذ نسخة احتياطية متسقة بأي وسيلة من الوسائل (نسخ الملفات ، mysqldump ، xtrabackup ، إلخ)

الخطة ج: لقطة LVM. بعد إجراء بعض عمليات التشفير ، يكون وقت التعطل للنسخة الاحتياطية أقل من دقيقة ، بغض النظر عن حجم قاعدة البيانات. أوقف mysqld ، قم بعمل اللقطة ، أعد تشغيل mysqld ، ثم انسخ اللقطة. يمكن أن تستغرق الخطوة الأخيرة وقتًا طويلاً ، لكن MySQL ليست معطلة.

الخطة د: لقطة لعبد - وقت تعطل صفر.

19
Rick James

بعض نقاط المشرف أولاً: هل تتصل للقيام ببروتوكول نقل الملفات أم أنك قمت بالدخول فيه وهو يموت؟ إذا كان ssh ، فتأكد من استخدام شاشة حتى تتمكن من الاستئناف بعد تعطل البث. إذا كان بروتوكول نقل الملفات ftp ، فتأكد من ضغطه/القطران قبل الإرسال.

جرب أيضًا المعلمة --opt أو --quick

--opt يقوم هذا الخيار بتشغيل مجموعة من الخيارات الإضافية لجعل عمليات التفريغ وإعادة التحميل أكثر كفاءة. على وجه التحديد ، يكافئ استخدام خيارات - إضافة طاولة إسقاط ، - إضافة أقفال ، - كل ، - سريع ، - إدراج إدراج إضافي ، - جداول قفل ، و - مفاتيح تعطيل - معًا. لاحظ أن هذا الخيار يجعل المخرجات أقل قابلية للحمل وأقل احتمالية لفهمها بواسطة أنظمة قواعد البيانات الأخرى.

- سريعة يخبر هذا الخيار mysqldump بكتابة إخراج التفريغ حيث يقرأ كل صف من الخادم ، والذي قد يكون مفيدًا للجداول الكبيرة. بشكل افتراضي ، يقرأ mysqldump جميع الصفوف من جدول في الذاكرة قبل كتابة الإخراج ؛ للجداول الكبيرة ، يتطلب هذا كميات كبيرة من الذاكرة ، مما قد يتسبب في فشل التفريغ.

15
David Hall

كنت أواجه مشاكل مع المهلات أثناء تفريغ قواعد البيانات الكبيرة أيضًا. لقد حللت أخيرًا إذا أرسلت أوامر فردية لكل جدول في ديسيبل وإلحاق كل شيء بملف واحد مثل هذا:

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
5
Patrick Heck

أعتقد أن السؤال هو حول كيفية الاستعادة بشكل أسرع من ملفات تفريغ mysqldump التي تم إنشاؤها ، وليس حل نسخ احتياطي مختلف.

إحدى الطرق ، يمكنك القيام بذلك هي عن طريق إنشاء مجموعات من الجداول في المخطط الخاص بك ، وإنشاء مستخدم DB منفصل لكل مجموعة ، ثم استخدام أذونات MySQL في النهاية لعدم السماح بإدراج الجداول لاستخدام جميع مستخدمي DB باستثناء مستخدم واحد.

هذه تقنية مجربة وسريعة ومتوازية تقريبًا ولكنها ليست متأكدة بنسبة 100 ٪ ، كم من الوقت سيستغرق الاستعادة من مقالب كبيرة مثل 500G أو نحو ذلك. ولكن في رأيي المتواضع ، تحتاج إلى شيء موازٍ. تحقق من الرابط أدناه للحصول على مثال.

[استعادة متوازية سريعة من مقالب SQL (mysqldump) لـ MySQL] [1]

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

"استعادة سريعة ومتوازية من مقالب SQL (mysqldump) لـ MySQL"

3
syed