Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Tiến độ không đứng yên nên lý do để nâng cấp lên phiên bản MySQL mới nhất ngày càng trở nên hấp dẫn. Cách đây không lâu, tại một trong những dự án của chúng tôi, đã đến lúc cập nhật cụm Percona Server 5.7 ấm cúng lên phiên bản 8. Tất cả điều này xảy ra trên nền tảng Ubuntu Linux 16.04. Cách thực hiện thao tác như vậy với thời gian ngừng hoạt động tối thiểu và những vấn đề chúng tôi gặp phải trong quá trình cập nhật - hãy đọc trong bài viết này.

Đào tạo

Bất kỳ bản cập nhật nào của máy chủ cơ sở dữ liệu rất có thể liên quan đến việc cấu hình lại cơ sở dữ liệu: những thay đổi về yêu cầu đối với giới hạn về tài nguyên hệ thống và việc sửa cấu hình cơ sở dữ liệu cần phải xóa các chỉ thị lỗi thời.

Trước khi cập nhật, chúng tôi chắc chắn sẽ tham khảo tài liệu chính thức:

Và hãy vạch ra một kế hoạch hành động:

  1. Sửa các tập tin cấu hình bằng cách loại bỏ các chỉ thị lỗi thời.
  2. Kiểm tra tính tương thích với các tiện ích.
  3. Cập nhật cơ sở dữ liệu nô lệ bằng cách cài đặt gói percona-server-server.
  4. Cập nhật bản gốc với cùng một gói.

Chúng ta hãy xem xét từng điểm của kế hoạch và xem điều gì có thể xảy ra sai sót.

QUAN TRỌNG! Quy trình cập nhật cụm MySQL dựa trên Galera có những điểm phức tạp riêng không được mô tả trong bài viết. Bạn không nên sử dụng hướng dẫn này trong trường hợp này.

Phần 1: Kiểm tra cấu hình

MySQL đã bị xóa trong phiên bản 8 query_cache. Thực ra anh ấy đã tuyên bố lỗi thời trở lại phiên bản 5.7, nhưng bây giờ đã xóa hoàn toàn. Theo đó, cần phải loại bỏ các chỉ thị liên quan. Và để lưu các yêu cầu vào bộ nhớ đệm, giờ đây bạn có thể sử dụng các công cụ bên ngoài - ví dụ: ProxyQuery.

Ngoài ra trong cấu hình còn có các chỉ thị lỗi thời về innodb_file_format. Nếu trong MySQL 5.7 có thể chọn định dạng InnoDB thì phiên bản thứ 8 đã hoạt động chỉ với định dạng Barracuda.

Kết quả của chúng tôi là loại bỏ các chỉ thị sau:

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

Để kiểm tra, chúng tôi sẽ sử dụng hình ảnh Docker của Percona Server. Chúng tôi sẽ đặt cấu hình máy chủ trong thư mục mysql_config_testvà bên cạnh nó chúng ta sẽ tạo các thư mục chứa dữ liệu và nhật ký. Ví dụ kiểm tra cấu hình máy chủ 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

Điểm mấu chốt: trong nhật ký Docker hoặc trong thư mục chứa nhật ký - tùy thuộc vào cấu hình của bạn - một tệp sẽ xuất hiện trong đó các lệnh có vấn đề sẽ được mô tả.

Đây là những gì chúng tôi đã có:

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.

Vì vậy, chúng tôi vẫn cần tìm ra cách mã hóa và thay thế lệnh đã lỗi thời expire-logs-days.

Phần 2: Kiểm tra cài đặt đang hoạt động

Tài liệu cập nhật chứa 2 tiện ích để kiểm tra tính tương thích của cơ sở dữ liệu. Việc sử dụng chúng giúp quản trị viên kiểm tra tính tương thích của cấu trúc dữ liệu hiện có.

Hãy bắt đầu với tiện ích mysqlcheck cổ điển. Đơn giản chỉ cần chạy:

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

Nếu không tìm thấy vấn đề gì, tiện ích sẽ thoát với mã 0:

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Ngoài ra, một tiện ích có sẵn trong các phiên bản hiện đại của MySQL vỏ mysql (trong trường hợp Percona thì đây là gói percona-mysql-shell). Nó là sự thay thế cho máy khách mysql cổ điển và kết hợp các chức năng của máy khách, trình soạn thảo mã SQL và các công cụ quản trị MySQL. Để kiểm tra máy chủ trước khi cập nhật, bạn có thể chạy các lệnh sau thông qua nó:

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

Dưới đây là những ý kiến ​​chúng tôi nhận được:

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Nói chung, không có gì quan trọng - chỉ cảnh báo về mã hóa (xem bên dưới). Kết quả thực hiện chung:

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Chúng tôi quyết định rằng bản cập nhật sẽ diễn ra mà không gặp vấn đề gì.

Lưu ý về các cảnh báo ở trên cho biết có vấn đề với mã hóa. Thực tế là UTF-8 trong MySQL cho đến gần đây UTF-8 không "đúng", vì nó chỉ lưu trữ 3 byte thay vì 4. Trong MySQL 8, điều này cuối cùng cũng được thực hiện quyết định sửa nó: bí danh utf8 sẽ sớm dẫn đến việc viết mã utf8mb4và các cột cũ trong bảng sẽ trở thành utf8mb3. Mã hóa thêm utf8mb3 sẽ bị xóa, nhưng không có trong bản phát hành này. Do đó, chúng tôi đã quyết định sửa các mã hóa đã có trên bản cài đặt DBMS đang chạy sau khi cập nhật nó.

Phần 3: Cập nhật máy chủ

Điều gì có thể xảy ra khi có một kế hoạch thông minh như vậy?.. Hiểu rõ rằng các sắc thái luôn xảy ra, chúng tôi đã tiến hành thử nghiệm đầu tiên trên cụm nhà phát triển MySQL.

Như đã đề cập, tài liệu chính thức đề cập đến vấn đề cập nhật máy chủ MySQL bằng các bản sao. Điểm mấu chốt là trước tiên bạn nên cập nhật tất cả các bản sao (nô lệ), vì MySQL 8 có thể sao chép từ phiên bản chính 5.7. Một số khó khăn nằm ở việc chúng ta sử dụng chế độ chủ <-> chủ, khi điều khiển từ xa ở chế độ chỉ đọc. Trên thực tế, lưu lượng chiến đấu đi đến một trung tâm dữ liệu và trung tâm thứ hai là trung tâm dự phòng.

Cấu trúc liên kết trông như thế này:

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Bản cập nhật phải bắt đầu bằng bản sao bản sao mysql dc 2, thạc sĩ mysql dc 2 и mysql replica dc 1, và kết thúc với máy chủ mysql master dc 1. Để đáng tin cậy hơn, chúng tôi đã dừng các máy ảo, chụp ảnh nhanh chúng và ngay trước khi cập nhật đã dừng sao chép bằng lệnh STOP SLAVE. Phần còn lại của bản cập nhật trông như thế này:

  1. Chúng tôi khởi động lại từng bản sao bằng cách thêm 3 tùy chọn vào cấu hình: skip-networking, skip-slave-start, skip-log-bin. Thực tế là việc cập nhật cơ sở dữ liệu sẽ tạo ra nhật ký nhị phân với các bản cập nhật cho bảng hệ thống. Các chỉ thị này đảm bảo rằng sẽ không có thay đổi nào đối với dữ liệu ứng dụng trong cơ sở dữ liệu và thông tin về việc cập nhật bảng hệ thống sẽ không được đưa vào nhật ký nhị phân. Điều này sẽ tránh được các vấn đề khi tiếp tục sao chép.
  2. Cài đặt gói percona-server-server. Điều quan trọng cần lưu ý là trong phiên bản MySQL 8 không bạn cần chạy lệnh mysqlupgrade sau khi cập nhật máy chủ.
  3. Sau khi khởi động thành công, chúng tôi khởi động lại máy chủ - không có các tham số đã được thêm vào đoạn đầu tiên.
  4. Chúng tôi đảm bảo rằng bản sao hoạt động thành công: kiểm tra SHOW SLAVE STATUS và xem các bảng có bộ đếm trong cơ sở dữ liệu ứng dụng có được cập nhật hay không.

Tất cả trông khá đơn giản: bản cập nhật dành cho nhà phát triển đã thành công. Được rồi, bạn có thể lên lịch cập nhật hàng đêm cho quá trình sản xuất một cách an toàn.

Không có nỗi buồn - chúng tôi đã cập nhật sản phẩm

Tuy nhiên, việc chuyển giao kinh nghiệm phát triển thành công sang sản xuất không phải là không có bất ngờ.

May mắn thay, quá trình cập nhật tự bắt đầu bằng các bản sao, vì vậy khi gặp khó khăn, chúng tôi đã dừng công việc và khôi phục bản sao từ ảnh chụp nhanh. Cuộc điều tra các vấn đề đã bị hoãn lại cho đến sáng hôm sau. Nhật ký chứa các mục sau:

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

Việc nghiên cứu kho lưu trữ của nhiều danh sách gửi thư khác nhau trên Google dẫn đến hiểu rằng sự cố này xảy ra do Lỗi MySQL. Mặc dù nhiều khả năng đây là lỗi tiện ích mysqlcheck и mysqlsh.

Hóa ra MySQL đã thay đổi cách biểu diễn dữ liệu cho các trường thập phân (int, tinyint, v.v.), vì vậy máy chủ mysql sử dụng một cách khác để lưu trữ chúng. Nếu cơ sở dữ liệu của bạn ban đầu đang ở phiên bản 5.5 hoặc 5.1, sau đó bạn cập nhật lên 5.7, thì bạn có thể cần phải thực hiện OPTIMIZE cho một số bảng. Sau đó, MySQL sẽ cập nhật các tệp dữ liệu, chuyển chúng sang định dạng lưu trữ hiện tại.

Bạn cũng có thể kiểm tra điều này bằng tiện ích 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',
...

Nếu field_type Nếu bạn có nó bằng 0 thì loại cũ sẽ được sử dụng trong bảng - bạn cần thực hiện OPTIMIZE. Tuy nhiên, nếu giá trị là 246 thì bạn đã có loại mới. Thông tin thêm về các loại có thể được tìm thấy trong mã số.

Hơn nữa, trong lỗi này Chúng tôi đang xem xét lý do có thể thứ hai mà chúng tôi đã bỏ qua: thiếu bảng InnoDB trong bảng hệ thống INNODB_SYS_TABLESPACES, nếu chúng, các bảng, được tạo trong phiên bản 5.1. Để tránh sự cố khi cập nhật, bạn có thể sử dụng tập lệnh SQL đính kèm.

Tại sao chúng tôi không gặp vấn đề như vậy trên dev? Cơ sở dữ liệu được sao chép định kỳ từ quá trình sản xuất - do đó, các bảng được tạo lại.

Thật không may, trên một cơ sở dữ liệu lớn đang hoạt động thực sự, bạn sẽ không thể chỉ lấy và thực thi một lệnh chung. OPTIMIZE. percona-toolkit sẽ trợ giúp ở đây: tiện ích pt-online-schema-change rất tuyệt vời cho hoạt động TỐI ƯU HÓA trực tuyến.

Kế hoạch cập nhật trông như thế này:

  1. Tối ưu hóa tất cả các bảng.
  2. Cập nhật cơ sở dữ liệu.

Để kiểm tra và đồng thời tìm ra thời gian cập nhật, chúng tôi đã tắt một trong các bản sao và chạy lệnh sau cho tất cả các bảng:

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

Các bảng được cập nhật mà không cần khóa dài do tiện ích này tạo một bảng tạm thời mới để sao chép dữ liệu từ bảng chính vào đó. Tại thời điểm cả hai bảng giống hệt nhau, bảng gốc sẽ bị khóa và thay thế bằng bảng mới. Trong trường hợp của chúng tôi, quá trình chạy thử nghiệm cho thấy rằng sẽ mất khoảng một ngày để cập nhật tất cả các bảng, nhưng việc sao chép dữ liệu đã khiến ổ đĩa tải quá nhiều.

Để tránh điều này, trong quá trình sản xuất, chúng tôi đã thêm đối số vào lệnh --sleep với giá trị 10 - tham số này điều chỉnh thời lượng chờ sau khi chuyển một lô dữ liệu sang bảng mới. Bằng cách này, bạn có thể giảm tải nếu ứng dụng đang chạy thực tế yêu cầu thời gian phản hồi.

Sau khi thực hiện tối ưu hóa, quá trình cập nhật đã thành công.

... nhưng không hoàn toàn!

Trong vòng nửa giờ sau khi cập nhật, khách hàng đã gặp sự cố. Cơ sở dữ liệu hoạt động rất kỳ lạ: định kỳ họ bắt đầu thiết lập lại kết nối. Đây là những gì nó trông giống như trong giám sát:

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

Ảnh chụp màn hình hiển thị biểu đồ răng cưa do thực tế là một số luồng máy chủ MySQL định kỳ bị lỗi. Lỗi xuất hiện trong ứng dụng:

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

Việc kiểm tra nhanh nhật ký cho thấy daemon mysqld không thể lấy được các tài nguyên cần thiết từ hệ điều hành. Trong khi phân loại lỗi, chúng tôi phát hiện trong hệ thống tập tin chính sách apparmor "mồ côi":

# 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

Các tệp này được tạo khi nâng cấp lên MySQL 5.7 vài năm trước và thuộc về gói đã bị xóa. Xóa các tập tin và khởi động lại dịch vụ apparmor đã giải quyết được vấn đề:

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

Kết luận

Bất kỳ thao tác nào, ngay cả những thao tác đơn giản nhất cũng có thể dẫn đến những sự cố không mong muốn. Và ngay cả việc có một kế hoạch được cân nhắc kỹ lưỡng cũng không phải lúc nào cũng đảm bảo kết quả như mong đợi. Giờ đây, bất kỳ kế hoạch cập nhật nào mà nhóm của chúng tôi thực hiện cũng bao gồm việc bắt buộc dọn dẹp các tệp không cần thiết có thể xuất hiện do các hành động gần đây.

Và với sự sáng tạo đồ họa không mấy chuyên nghiệp này, tôi muốn gửi lời cảm ơn sâu sắc đến Percona vì những sản phẩm tuyệt vời của họ!

Cập nhật MySQL (Percona Server) từ 5.7 lên 8.0

PS

Đọc thêm trên blog của chúng tôi:

Nguồn: www.habr.com

Thêm một lời nhận xét