ทำไม MySQL ตารางขัดข้อง ฉันจะป้องกันมันได้อย่างไร


9

ฉันเป็นผู้ดูแลระบบของไซต์Moodleที่ตารางผู้ใช้เสียหายและกลายเป็นใช้ไม่ได้

โชคดีที่ความเรียบง่ายREPAIR TABLE mdl_userทำให้มันทำงานได้อีกครั้ง สิ่งนี้คือฉันไม่รู้ว่าทำไมมันจึงล้มเหลวจริง ๆ และทำให้มันใช้ไม่ได้และฉันต้องการให้แน่ใจว่าฉันจะเตรียมตัวดีขึ้นในครั้งต่อไป

ฉันไม่ใช่ DBA ที่มีประสบการณ์อย่างถี่ถ้วน - ฉันเป็นเพียงนักพัฒนาที่ทำสิ่งต่างๆมากมายดังนั้นโปรดอดทนกับฉัน

ฉันสามารถกู้คืนข้อมูลสำรอง แต่ฉันเดาว่ามีวิธีการป้องกันการล่ม

ตารางเหล่านั้นคือ utf8_general_ci และใช้ MyISAM

ทำไมตาราง MySQL ผิดพลาด ฉันจะทำอย่างไรเพื่อป้องกันไม่ให้เกิดขึ้น

คำตอบ:


11

มันค่อนข้างง่ายสำหรับตาราง MyISAM ที่จะพัง

ในส่วนหัวของทุกตาราง MyISAM เป็นตัวนับที่ติดตามจำนวนไฟล์ที่เปิดที่จับได้ที่มีต่อตาราง

หากคุณเริ่มต้น mysql และหมายเลขในส่วนหัวไม่ตรงกับจำนวนไฟล์ที่ถูกจัดการจริง ๆ mysqld จะรักษาตารางนั้นไม่ทำงาน

ถ้าง่ายทำให้มันทำงานอีกครั้งทุกครั้งโดยไม่สูญเสียของข้อมูลนี้อาจบ่งบอกว่าคุณมีเว็บไซต์ค้ามากอย่างที่เขียนไปREPAIR TABLE mdl_usermdl_user

หากต้องการหลายสิบตารางREPAIR TABLEฉันจะแปลงตารางทั้งหมดเป็น InnoDB อย่างไรก็ตามหากmdl_userตารางเป็นตารางเดียวที่มีปัญหานี้มีบางสิ่งที่คุณสามารถทำได้ (สำหรับตัวอย่างนี้สมมติว่าฐานข้อมูลเป็นmoodle)

หากคุณต้องการให้ตารางทั้งหมดเป็น MyISAM

ขั้นตอนที่ 01: สร้างสคริปต์ซ่อมแซมตาราง

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

ขั้นตอนที่ 02: ประกาศสคริปต์ซ่อมแซมเป็นไฟล์เริ่มต้น

เพิ่มไปยัง /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

ขั้นตอนที่ 03: เริ่ม mysql ใหม่

การรีสตาร์ท mysql ทุกครั้งจะเรียกสคริปต์ซ่อมแซมตาราง

หากคุณต้องการให้ตารางทั้งหมดกลายเป็น InnoDB

เรียกใช้รหัสนี้เพื่อสร้างสคริปต์การแปลงข้อมูลจำนวนมากของตาราง MyISAM เป็น InnoDB และดู

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

เมื่อคุณพอใจกับเนื้อหาของสคริปต์การแปลงแล้วเรียกใช้

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

อัพเดท 2012-03-15 14:00 EDT

@Kevinในขณะที่ใช้ MyISAM จะเกิดอะไรขึ้นถ้า Disk Out isuue ของคุณหมด?

นี่คือสิ่งที่ต้องพิจารณา: ตามคู่มือการศึกษาการรับรอง MySQL 5.0 ,

ป้อนคำอธิบายรูปภาพที่นี่

bulletpoint # 11กล่าวว่าสิ่งต่อไปนี้ในหน้า 408,409 มาตรา 29.2:

หากคุณใช้พื้นที่ดิสก์ไม่เพียงพอในขณะที่เพิ่มแถวลงในตาราง MyISAM จะไม่มีข้อผิดพลาดเกิดขึ้น เซิร์ฟเวอร์หยุดการทำงานชั่วคราวจนกว่าพื้นที่ว่างจะพร้อมใช้งานจากนั้นดำเนินการให้เสร็จสิ้น

เมื่อคุณใช้พื้นที่ดิสก์หมดอย่าเพิ่งปิดหรือฆ่า mysql จำนวนของการจัดการไฟล์ที่เปิดใน MyISAM ใด ๆ ที่ใช้ในปัจจุบันจะไม่ถูกล้างออก ดังนั้นตาราง MyISAM ถูกทำเครื่องหมายว่าขัดข้อง หากคุณสามารถเพิ่มเนื้อที่ว่างในดิสก์ในโวลุ่มข้อมูลโดยที่ mysqld ยังคงทำงานอยู่ mysqld จะเป็นทหารเมื่อมีพื้นที่ว่างในดิสก์


การตอบสนองที่ยอดเยี่ยม ไม่ทราบว่าบิตของไฟล์จัดการได้อย่างไรและคุณได้แก้ไขแล้วว่าฉันจะป้องกัน (หรือซ่อมแซมโดยอัตโนมัติ) ได้อย่างไรในกรณีที่มีบางอย่างผิดปกติ ข้อเสนอแนะเพื่อความปลอดภัยใด ๆ หากเว็บไซต์ที่จริงแล้วมีจำนวนมากเขียนไปยัง mdl_user (หรือตารางอื่น ๆ )?
AeroCross

คุณควรทำสามสิ่ง: 1) เพิ่ม RAM, 2) เพิ่ม max_connections, 3) เปลี่ยนเป็น InnoDB
RolandoMySQLDBA

Noob ที่นี่ ฉันจะ "เรียกใช้" รหัสนี้ที่ไหน จากไฟล์ที่อัพโหลดไปยังเซิร์ฟเวอร์หรือจากบรรทัดคำสั่งบางอย่าง?
UncaughtTypeError

0

ฉันจัดการไซต์ moodle บน mysql และสาเหตุที่พบบ่อยที่สุดของตารางเสียหายสำหรับเรานั้นมีพื้นที่ดิสก์เหลืออยู่


@RolandoMySQLDBA - ใช่พื้นที่ดิสก์เป็นปัญหาแน่นอน (เกี่ยวข้องกับกระบวนการอื่น ๆ และปรัชญาการจัดการทั่วไป) น่าเสียดายที่เราไม่เห็นปัญหาแก้ไขตัวเองเมื่อล้างพื้นที่หรือไม่สามารถแก้ไขได้ในเวลาที่เหมาะสม การตอบสนองของฉันเป็นเพียงการชี้ให้เห็นว่าด้วยอินสแตนซ์ moodle / mysql ของเราปัญหาพื้นที่ดิสก์อาจทำให้เกิดปัญหาตารางโดยไม่คำนึงถึงสิ่งที่ควรจะทำ mysql / myisam
Kevin

-3

ฉันพบหนึ่งบรรทัดที่ดีในการแปลงตารางทั้งหมดเป็น InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName

รหัสอาจใช้ได้ แต่ก็ไม่ตอบคำถามส่วนแรก (เพราะเหตุใดตาราง MySQL จึงผิดพลาด) ถ้าคุณหมายความว่ามันตอบส่วนที่สอง (วิธีการป้องกันมันได้อย่างไร) เพิ่มคำอธิบายเพิ่มเติมได้โปรด
ypercubeᵀᴹ

เพิ่มรายละเอียดเพิ่มเติม การรันสิ่งนี้จะแปลงตารางทั้งหมดในฐานข้อมูลหรือไม่ หรือเซิร์ฟเวอร์ทั้งหมด จะเกิดอะไรขึ้นหากตารางไม่สามารถแปลงได้และเราได้รับข้อผิดพลาด เป็นไปได้ไหมที่เราจะจบลงด้วยการเปลี่ยนตารางและเหลือใน MyiSAM บ้าง? โดยทั่วไปแล้วสิ่งใดที่ DBA ควรพิจารณาก่อนใช้งานสิ่งนี้
ypercubeᵀᴹ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.