การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

ความคืบหน้าไม่หยุดนิ่ง ดังนั้นเหตุผลในการอัพเกรดเป็น MySQL เวอร์ชันล่าสุดจึงมีความน่าสนใจมากขึ้นเรื่อยๆ ไม่นานมานี้ หนึ่งในโครงการของเรา ถึงเวลาอัปเดตคลัสเตอร์ Percona Server 5.7 ที่สะดวกสบายเป็นเวอร์ชัน 8 ทั้งหมดนี้เกิดขึ้นบนแพลตฟอร์ม Ubuntu Linux 16.04 วิธีดำเนินการดังกล่าวโดยมีเวลาหยุดทำงานน้อยที่สุดและปัญหาใดที่เราพบระหว่างการอัปเดต - อ่านในบทความนี้

การอบรม

การอัพเดตเซิร์ฟเวอร์ฐานข้อมูลมักจะเกี่ยวข้องกับการกำหนดค่าฐานข้อมูลใหม่: การเปลี่ยนแปลงข้อกำหนดสำหรับขีดจำกัดทรัพยากรระบบ และการแก้ไขการกำหนดค่าฐานข้อมูลที่ต้องล้างคำสั่งที่ล้าสมัย

ก่อนที่จะอัปเดต เราจะอ้างอิงถึงเอกสารอย่างเป็นทางการอย่างแน่นอน:

และมาจัดทำแผนปฏิบัติการกัน:

  1. แก้ไขไฟล์การกำหนดค่าโดยการลบคำสั่งที่ล้าสมัย
  2. ตรวจสอบความเข้ากันได้กับยูทิลิตี้
  3. อัพเดตฐานข้อมูลทาสโดยการติดตั้งแพ็คเกจ percona-server-server.
  4. อัพเดตต้นแบบด้วยแพ็คเกจเดียวกัน

ลองดูที่แต่ละจุดของแผนและดูว่ามีอะไรผิดพลาดบ้าง

สำคัญ! ขั้นตอนการอัปเดตคลัสเตอร์ MySQL ที่ใช้ Galera มีรายละเอียดปลีกย่อยของตัวเองที่ไม่ได้อธิบายไว้ในบทความ คุณไม่ควรใช้คำแนะนำนี้ในกรณีนี้

ส่วนที่ 1: การตรวจสอบการกำหนดค่า

MySQL ถูกลบออกในเวอร์ชัน 8 query_cache. จริงๆแล้วเขาเป็น ประกาศล้าสมัย ย้อนกลับไปในเวอร์ชัน 5.7 แต่ตอนนี้ ลบออกอย่างสมบูรณ์. ดังนั้นจึงจำเป็นต้องลบคำสั่งที่เกี่ยวข้องออก และในการแคชคำขอ ตอนนี้คุณสามารถใช้เครื่องมือภายนอกได้ - ตัวอย่างเช่น พร็อกซี SQL.

นอกจากนี้ในการกำหนดค่ายังมีคำสั่งที่ล้าสมัยอยู่ innodb_file_format. หากใน MySQL 5.7 สามารถเลือกรูปแบบ InnoDB ได้แสดงว่าเวอร์ชัน 8 ใช้งานได้แล้ว ในรูปแบบ Barracuda เท่านั้น.

ผลลัพธ์ของเราคือการลบคำสั่งต่อไปนี้:

  • query_cache_type, query_cache_limit и query_cache_size;
  • innodb_file_format и innodb_file_format_max.

ในการตรวจสอบ เราจะใช้อิมเมจ Docker ของ Percona Server เราจะวางการกำหนดค่าเซิร์ฟเวอร์ไว้ในไดเร็กทอรี mysql_config_testและถัดจากนั้นเราจะสร้างไดเร็กทอรีสำหรับข้อมูลและบันทึก ตัวอย่างการทดสอบการกำหนดค่าเซิร์ฟเวอร์ Percona:

mkdir -p {mysql_config_test,mysql_data,mysql_logs}
cp -r /etc/mysql/conf.d/* mysql_config_test/
docker run  --name some-percona -v $(pwd)/mysql_config_test:/etc/my.cnf.d/  -v $(pwd)/mysql_data/:/var/lib/mysql/ -v $(pwd)/mysql_logs/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -d percona:8-centos

บรรทัดล่าง: ทั้งในบันทึกของนักเทียบท่าหรือในไดเร็กทอรีที่มีบันทึก - ขึ้นอยู่กับการกำหนดค่าของคุณ - ไฟล์จะปรากฏขึ้นโดยจะมีการอธิบายคำสั่งที่มีปัญหา

นี่คือสิ่งที่เรามี:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] The syntax 'expire-logs-days' is deprecated and will be removed in a future release. Please use binlog_expire_logs_seconds instead.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.

ดังนั้นเราจึงยังคงจำเป็นต้องค้นหาการเข้ารหัสและแทนที่คำสั่งที่ล้าสมัย expire-logs-days.

ส่วนที่ 2: การตรวจสอบการติดตั้งที่ใช้งานได้

เอกสารการอัพเดตประกอบด้วย 2 ยูทิลิตี้สำหรับตรวจสอบความเข้ากันได้ของฐานข้อมูล การใช้งานช่วยให้ผู้ดูแลระบบตรวจสอบความเข้ากันได้ของโครงสร้างข้อมูลที่มีอยู่

เริ่มจากยูทิลิตี้ mysqlcheck แบบคลาสสิกกันก่อน เพียงเรียกใช้:

mysqlcheck -u root -p --all-databases --check-upgrade

หากไม่พบปัญหา ยูทิลิตี้นี้จะออกด้วยรหัส 0:

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

นอกจากนี้ ยังมียูทิลิตี้นี้ใน MySQL เวอร์ชันทันสมัยอีกด้วย mysql-shell (ในกรณีของ Percona นี่คือแพ็คเกจ percona-mysql-shell). เป็นการทดแทนไคลเอนต์ mysql แบบคลาสสิกและรวมฟังก์ชันของไคลเอนต์ โปรแกรมแก้ไขโค้ด SQL และเครื่องมือการดูแลระบบ MySQL หากต้องการตรวจสอบเซิร์ฟเวอร์ก่อนอัปเดต คุณสามารถรันคำสั่งต่อไปนี้ผ่านเซิร์ฟเวอร์ได้:

mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=/etc/mysql/my.cnf

นี่คือความคิดเห็นที่เราได้รับ:

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

โดยทั่วไปไม่มีอะไรสำคัญ - มีเพียงคำเตือนเกี่ยวกับการเข้ารหัสเท่านั้น (ดูด้านล่าง). ผลการดำเนินการโดยรวม:

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

เราตัดสินใจว่าการอัปเดตควรจะดำเนินไปโดยไม่มีปัญหา

หมายเหตุเกี่ยวกับคำเตือนข้างต้นซึ่งระบุถึงปัญหาในการเข้ารหัส ความจริงก็คือ UTF-8 ใน MySQL จนกระทั่งเมื่อไม่นานมานี้ ไม่ใช่ UTF-8 "จริง"เนื่องจากมันเก็บได้เพียง 3 ไบต์แทนที่จะเป็น 4 ในที่สุดใน MySQL 8 ก็เป็นเช่นนี้ ตัดสินใจที่จะแก้ไขมัน: นามแฝง utf8 จะนำไปสู่การเข้ารหัสในไม่ช้า utf8mb4และคอลัมน์เก่าในตารางจะกลายเป็น utf8mb3. การเข้ารหัสเพิ่มเติม utf8mb3 จะถูกลบออก แต่ไม่ใช่ในรุ่นนี้ ดังนั้นเราจึงตัดสินใจแก้ไขการเข้ารหัสที่มีอยู่แล้วในการติดตั้ง DBMS ที่ทำงานอยู่หลังจากอัปเดตแล้ว

ส่วนที่ 3: การอัปเดตเซิร์ฟเวอร์

จะเกิดอะไรขึ้นเมื่อมีแผนอันชาญฉลาดเช่นนั้น.. ด้วยความเข้าใจอย่างถ่องแท้ว่าความแตกต่างเล็กๆ น้อยๆ เกิดขึ้นได้เสมอ เราจึงทำการทดลองครั้งแรกกับคลัสเตอร์ MySQL dev

ดังที่ได้กล่าวมาแล้ว เอกสารอย่างเป็นทางการ ครอบคลุมถึงปัญหาการอัปเดตเซิร์ฟเวอร์ MySQL ด้วยเรพลิกา สิ่งที่สำคัญที่สุดคือคุณควรอัปเดตเรพลิกาทั้งหมด (สเลฟ) ก่อน เนื่องจาก MySQL 8 สามารถจำลองจากมาสเตอร์เวอร์ชัน 5.7 ได้ ปัญหาบางประการอยู่ที่การที่เราใช้โหมดนี้ มาสเตอร์ <-> มาสเตอร์เมื่อรีโมทต้นแบบอยู่ในโหมด อ่านอย่างเดียว. นั่นคือในความเป็นจริง การรับส่งข้อมูลการต่อสู้ไปที่ศูนย์ข้อมูลแห่งหนึ่ง และศูนย์ข้อมูลที่สองเป็นศูนย์ข้อมูลสำรอง

โทโพโลยีมีลักษณะดังนี้:

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

การอัปเดตต้องเริ่มต้นด้วยการจำลอง mysql จำลอง dc2, mysql มาสเตอร์ ดีซี 2 и mysql replica dc 1และปิดท้ายด้วยเซิร์ฟเวอร์ mysql master dc 1 เพื่อให้เชื่อถือได้มากขึ้น เราได้หยุดเครื่องเสมือน ถ่ายภาพสแนปชอตของเครื่องเหล่านั้น และทันทีก่อนที่การอัปเดตจะหยุดการจำลองด้วยคำสั่ง STOP SLAVE. การอัปเดตที่เหลือมีลักษณะดังนี้:

  1. เรารีสตาร์ทแต่ละเรพลิกาโดยเพิ่ม 3 ตัวเลือกให้กับการกำหนดค่า: skip-networking, skip-slave-start, skip-log-bin. ความจริงก็คือการอัพเดตฐานข้อมูลจะสร้างบันทึกไบนารีพร้อมการอัพเดตตารางระบบ คำสั่งเหล่านี้รับประกันว่าจะไม่มีการเปลี่ยนแปลงข้อมูลแอปพลิเคชันในฐานข้อมูล และข้อมูลเกี่ยวกับการอัปเดตตารางระบบจะไม่รวมอยู่ในบันทึกไบนารี วิธีนี้จะหลีกเลี่ยงปัญหาเมื่อดำเนินการจำลองแบบต่อ
  2. กำลังติดตั้งแพ็คเกจ percona-server-server. สิ่งสำคัญคือต้องทราบว่าใน MySQL เวอร์ชัน 8 ไม่ คุณต้องรันคำสั่ง mysqlupgrade หลังจากอัพเดตเซิร์ฟเวอร์
  3. หลังจากเริ่มต้นได้สำเร็จ เราจะรีสตาร์ทเซิร์ฟเวอร์อีกครั้ง - โดยไม่มีพารามิเตอร์ที่เพิ่มไว้ในย่อหน้าแรก
  4. ตรวจสอบให้แน่ใจว่าการจำลองแบบทำงานได้สำเร็จ: ตรวจสอบ SHOW SLAVE STATUS และดูว่าตารางที่มีตัวนับในฐานข้อมูลแอปพลิเคชันได้รับการอัปเดตแล้ว

ทุกอย่างดูเรียบง่าย: การอัปเดต dev สำเร็จแล้ว ตกลง คุณสามารถกำหนดเวลาการอัปเดตการผลิตทุกคืนได้อย่างปลอดภัย

ไม่มีความโศกเศร้า - เราอัปเดตผลิตภัณฑ์แล้ว

อย่างไรก็ตาม การถ่ายโอนประสบการณ์การพัฒนาที่ประสบความสำเร็จไปสู่การผลิตไม่ใช่เรื่องน่าประหลาดใจเลย

โชคดีที่กระบวนการอัปเดตนั้นเริ่มต้นด้วยการจำลอง ดังนั้นเมื่อเราประสบปัญหา เราก็หยุดงานและกู้คืนแบบจำลองจากสแน็ปช็อต การสอบสวนปัญหาถูกเลื่อนออกไปเป็นเช้าวันรุ่งขึ้น บันทึกมีรายการต่อไปนี้:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] table: t1 has 19 columns but InnoDB dictionary has 20 columns
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Error in fixing SE data for db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Failed to Populate DD tables.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Aborting

การค้นคว้าข้อมูลที่เก็บถาวรของรายชื่อผู้รับจดหมายต่างๆ บน Google ทำให้เกิดความเข้าใจว่าปัญหานี้เกิดขึ้นเนื่องจาก ข้อผิดพลาด MySQL. แม้ว่านี่จะเป็นข้อผิดพลาดด้านอรรถประโยชน์มากกว่าก็ตาม mysqlcheck и mysqlsh.

ปรากฎว่า MySQL เปลี่ยนวิธีการแสดงข้อมูลสำหรับเขตข้อมูลทศนิยม (int, Tinyint ฯลฯ) ดังนั้นเซิร์ฟเวอร์ mysql จึงใช้วิธีอื่นในการจัดเก็บข้อมูล หากฐานข้อมูลของคุณ เริ่มแรก อยู่ในเวอร์ชัน 5.5 หรือ 5.1 จากนั้นคุณอัปเดตเป็น 5.7 แล้วคุณอาจต้องทำ OPTIMIZE สำหรับบางโต๊ะ จากนั้น MySQL จะอัปเดตไฟล์ข้อมูลโดยถ่ายโอนเป็นรูปแบบที่จัดเก็บข้อมูลปัจจุบัน

คุณสามารถตรวจสอบสิ่งนี้ได้ด้วยยูทิลิตี้นี้ mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # формат поля
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'you_deciaml_column',
...

ถ้า field_type หากคุณมีค่าเท่ากับ 0 แสดงว่าตารางจะใช้แบบเก่า - คุณต้องดำเนินการ OPTIMIZE. อย่างไรก็ตาม หากค่าเป็น 246 แสดงว่าคุณมีประเภทใหม่แล้ว ข้อมูลเพิ่มเติมเกี่ยวกับประเภทสามารถพบได้ใน รหัส.

นอกจากนี้ใน ข้อผิดพลาดนี้ เรากำลังพิจารณาเหตุผลที่เป็นไปได้ประการที่สอง ซึ่งข้ามเราไป: การไม่มีตาราง InnoDB ในตารางระบบ INNODB_SYS_TABLESPACESหากตารางถูกสร้างขึ้นในเวอร์ชัน 5.1 คุณสามารถใช้เพื่อหลีกเลี่ยงปัญหาในการอัพเดต สคริปต์ SQL ที่แนบมา.

ทำไมเราไม่พบปัญหาดังกล่าวใน dev? ฐานข้อมูลจะถูกคัดลอกเป็นระยะจากการผลิต - ดังนั้น ตารางจะถูกสร้างขึ้นใหม่.

น่าเสียดายที่บนฐานข้อมูลขนาดใหญ่ที่ใช้งานได้ดี คุณจะไม่สามารถดำเนินการและดำเนินการแบบสากลได้ OPTIMIZE. percona-toolkit จะช่วยได้ที่นี่: ยูทิลิตี้ pt-online-schema-change นั้นยอดเยี่ยมสำหรับการดำเนินการ OPTIMIZE ออนไลน์

แผนที่อัปเดตมีลักษณะดังนี้:

  1. เพิ่มประสิทธิภาพตารางทั้งหมด
  2. อัพเดตฐานข้อมูล

เพื่อตรวจสอบและค้นหาเวลาอัปเดตในเวลาเดียวกัน เราได้ปิดการใช้งานหนึ่งในเรพลิกาและรันคำสั่งต่อไปนี้สำหรับตารางทั้งหมด:

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

ตารางได้รับการอัปเดตโดยไม่มีการล็อคที่ยาวเนื่องจากยูทิลิตี้สร้างตารางชั่วคราวใหม่เพื่อคัดลอกข้อมูลจากตารางหลัก ในขณะที่ทั้งสองตารางเหมือนกัน ตารางเดิมจะถูกล็อคและแทนที่ด้วยตารางใหม่ ในกรณีของเรา การทดสอบแสดงให้เห็นว่าจะใช้เวลาประมาณหนึ่งวันในการอัปเดตตารางทั้งหมด แต่การคัดลอกข้อมูลทำให้ดิสก์มีภาระมากเกินไป

เพื่อหลีกเลี่ยงปัญหานี้ ในการผลิตเราได้เพิ่มอาร์กิวเมนต์ให้กับคำสั่ง --sleep ด้วยค่า 10 - พารามิเตอร์นี้จะปรับระยะเวลารอหลังจากถ่ายโอนชุดข้อมูลไปยังตารางใหม่ วิธีนี้ทำให้คุณสามารถลดภาระได้หากแอปพลิเคชันที่ทำงานอยู่จริงต้องการเวลาตอบสนอง

หลังจากดำเนินการปรับให้เหมาะสมแล้ว การอัปเดตก็สำเร็จ

...แต่ยังไม่หมด!

ภายในครึ่งชั่วโมงหลังจากการอัพเดต ลูกค้าก็ประสบปัญหา ฐานข้อมูลทำงานแปลกมาก: เริ่มทำงานเป็นระยะ รีเซ็ตการเชื่อมต่อ. นี่คือสิ่งที่ดูเหมือนในการตรวจสอบ:

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

ภาพหน้าจอแสดงกราฟฟันเลื่อยเนื่องจากเธรดเซิร์ฟเวอร์ MySQL บางเธรดขัดข้องเป็นระยะโดยมีข้อผิดพลาด ข้อผิดพลาดปรากฏในแอปพลิเคชัน:

[PDOException] SQLSTATE[HY000] [2002] Connection refused

การตรวจสอบบันทึกอย่างรวดเร็วพบว่า mysqld daemon ไม่สามารถรับทรัพยากรที่จำเป็นจากระบบปฏิบัติการได้ ขณะแยกแยะข้อผิดพลาด เราค้นพบในระบบ ไฟล์นโยบาย apparmor "orphan":

# dpkg -S /etc/apparmor.d/cache/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/cache/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/local/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/local/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/usr.sbin.mysqld
mysql-server-5.7: /etc/apparmor.d/usr.sbin.mysqld
# dpkg -l mysql-server-5.7
rc  mysql-server-5.7 5.7.23-0ubuntu0.16.04.1      amd64

ไฟล์เหล่านี้ถูกสร้างขึ้นเมื่ออัปเกรดเป็น MySQL 5.7 เมื่อสองสามปีก่อนและเป็นของแพ็คเกจที่ถูกลบออก การลบไฟล์และการรีสตาร์ทบริการ apparmor ช่วยแก้ปัญหาได้:

systemctl stop apparmor
rm /etc/apparmor.d/cache/usr.sbin.mysqld
rm /etc/apparmor.d/local/usr.sbin.mysqld
rm /etc/apparmor.d/usr.sbin.mysqld
systemctl start apparmor

ในข้อสรุป

แม้แต่การดำเนินการที่ง่ายที่สุดก็สามารถนำไปสู่ปัญหาที่ไม่คาดคิดได้ และแม้แต่การมีแผนงานที่คิดมาอย่างดีก็ไม่ได้รับประกันผลลัพธ์ที่คาดหวังเสมอไป ขณะนี้ แผนการอัปเดตใดๆ ที่ทีมของเราได้รวมการบังคับล้างไฟล์ที่ไม่จำเป็นซึ่งอาจปรากฏขึ้นอันเป็นผลมาจากการกระทำล่าสุด

และด้วยความคิดสร้างสรรค์กราฟิกที่ไม่เป็นมืออาชีพมากนัก ฉันอยากจะขอบคุณ Percona อย่างมากสำหรับผลิตภัณฑ์ที่ยอดเยี่ยมของพวกเขา!

การอัปเกรด MySQL (เซิร์ฟเวอร์ Percona) จาก 5.7 เป็น 8.0

PS

อ่านเพิ่มเติมในบล็อกของเรา:

ที่มา: will.com

เพิ่มความคิดเห็น