Share
Embed
レガシーサービスのMySQLバージョンアップ(5.1 -> 5.7)とRDS化
MyNA(日本MySQLユーザ会) 望年LT大会2020@オンライン
https://mysql.connpass.com/event/196850/
で当時発表した
「レガシーサービスのMySQLバージョンアップ(5.1 -> 5.7)とRDS化」
の資料になります。
その後、本RDS移行から数年経過し、公開しても特に問題無いのではないかと判断した事、
同じようなレガシーな環境の方がいらっしゃるかもしれないため、今更ですが公開しておきます。
Shigeki SUGAI
December 11, 2020
Transcript
33 slides
-
某サービスについて 古いオンプレのサービスがありまして、歴史的な経緯により、2009年当時にMySQL 4.0か ら 5.1にバージョンアップした後、 この10年ほどずっとMySQL 5.1で運用していました。 様々な事情により、AWS RDSに持っていく必要が出てきました。 が、MySQL
5.1のままだと、Amazon RDSに入れることが出来ません。。 (RDSはMySQL 5.6以上をサポート) -
某サービスのMySQL 5.1の特徴 ストレージエンジンはMyISAM 深遠な理由により、ずっとMyISAMとなっていました 今回のバージョンアップを機に、InnoDBに変更しました 文字コードは5.1 のUTF8 utf8mb4ではない が、utf8mb4の絵文字「 」「
」が入っている状態 当時の何かしらの理由により、範囲外の文字列を入れられるパッチを当てていた模 様。。 -
某サービスのMySQL 5.1の特徴 日付型の扱いがゆるふわ テーブルのdatetime型のデフォルト値はだいたい 0000-00-00 00:00 などとなっ ていた この5.1 DBとは別ですが、別の機能で使っているDBは未だにMySQL
4.0のMyISAM マ ージテーブルなども現役で動いている -
5.7移行にあたっての前提条件 関係者が多く、長時間の停止メンテナンスは難しい… 具体的には丸一日停止して閲覧が全部止まるようなのはNG 書き込み停止は長くても数時間程度まで 書き込みメンテナンス中も閲覧だけは極力続けたい せっかく 5.1 -> 5.7 に上げるのであれば
sql_mode なども厳格にしたい 5.1 -> 5.5 -> 5.6 -> 5.7 のようにレプリケーションのチェーンをするオンプレのサーバ リソースはない… せっかくなので、 5.1で3つに分かれていたDBを1つのDBに集約したい -
ダブルライト方式(人力バイナリログ機能)の実装 こんな感じで、専用の人力バイナリログDBに更新されたレコードが入るようになりました mysql> select * from replication2020092903 where sync =
0 group by model limit 100; +-------+-----------------------------------------+--------+-------------+------+ | id | model | method | primary_key | sync | +-------+-----------------------------------------+--------+-------------+------+ | 18321 | Service::Data::Article | insert | xxxxxxxxxx | 0 | | 18321 | Service::Data::Article | insert | xxxxxxxxxx | 0 | | 19801 | Service::Data::ArticleChild | delete | xxxxxxxxxx | 0 | | 15675 | Service::Data::ArticleReserve | insert | xxxxxxxxxx | 0 | | 17152 | Service::Data::Captcha | insert | xxxxxxxxxx | 0 | | 4 | Service::Data::Draft | update | xxxxxxxxxx | 0 | | 3508 | Service::Data::MailAliasPostLog | insert | xxxxxxxxxx | 0 | | 99 | Service::Data::QueueAlertComment | update | xxxxxxxxxx | 0 | | 430 | Service::Data::QueueAlertFanBlogUpdates | insert | xxxxxxxxxx | 0 | | 3504 | Service::Data::QueueBuildArticle | insert | xxxxxxxxxx | 0 | | 15689 | Service::Data::QueueMobileDevicePush | insert | xxxxxxxxxx | 0 | | 245 | Service::Data::SpamChecker | insert | xxxxxxxxxx | 0 | | 17219 | Service::Data::TwitterAccount | update | xxxxxxxxxx | 0 | | 18147 | Service::Data::Upload | update | xxxxxxxxxx | 0 | | 16935 | Service::Data::UploadArticle | insert | xxxxxxxxxx | 0 | -
ダブルライト方式のためのログDB用のレプリケーション フィルター設定追加 MySQL 5.7からの新機能として、再起動不要でオンラインでレプリケーションする対象DBが 増やせるということを知り、無駄なメンテナンスを取らずに済みました…。 助かりました。。 mysql> CHANGE REPLICATION FILTER
REPLICATE_DO_DB = (service_article, service_replication); Query OK, 0 rows affected (0.00 sec) たぶん知ってればなんてことは無かったのですが・・・ -
ダブルライト方式(人力バイナリログ機能)の追従開始 手動レプリの不整合の解決をして、落ち着いてきた段階でこんな感じで1時間単位で手動でレ プリ同期していきました for x in $(seq -w 0 23)
do TABLE_NAME=replication20201012$x echo === $x === echo /var/hoge/src/service/bin/bl.scripts exec replication_do $TABLE_NAME sleep 10; /var/hoge/src/service/bin/bl.scripts exec replication_do $TABLE_NAME done; -
5.1 mysqldumpを 5.7へインポートする際の工夫 5.1のmysqldumpを 5.7 にインポートする際には、明示的に --default-character- set=utf8mb4 を付ける必要があった $
/tmp/20200928/20200928/service_new$ for x in `ls *.gz` ;do echo === $x ===; zcat $x | mysql --default-character-set=utf8mb4 -uroot service_new ; done; これをしないと「 」「 」などがすべて ? になって壊れてしまう -
負荷テストで見つかったslow_logの一部 ファイル名検索でインデックスが効かずにフルインデックススキャンになってしまう問題の 修正など -- before mysql> explain SELECT id, cache_height_thumbnail,
member_id, filename, cache_width, object_id, timestamp, createstamp, cache_size, cache_media_type, title, type, service_id, cache_height, cache_width_thumbnail FROM upload WHERE service_id = '6945629' AND filename LIKE '%html%' ORDER BY id DESC LIMIT 0, 1000; +----+-------------+--------+------------+-------+------------------------------------------------------------+---------+---------+------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+-------+------------------------------------------------------------+---------+---------+------+--------+----------+-------------+ | 1 | SIMPLE | upload | NULL | index | service_id__id,service_id,service_id__createstamp,service_id__filename | PRIMARY | 4 | NULL | 125684 | 0.09 | Using where | +----+-------------+--------+------------+-------+------------------------------------------------------------+---------+---------+------+--------+----------+-------------+ -- after mysql> explain SELECT id, service_id, cache_height_thumbnail, member_id, filename, cache_width, object_id, timestamp, createstamp, cache_size, cache_media_type, title, type, service_id, cache_height, cache_width_thumbnail FROM upload WHERE service_id = '6945629' AND filename LIKE '%html%' ORDER BY createstamp DESC LIMIT 0, 1000; +----+-------------+--------+------+------------------------------------------+----------------------+---------+-------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+------------------------------------------+----------------------+---------+-------+--------+-------------+ | 1 | SIMPLE | upload | ref | service_id__id,service_id,service_id__createstamp | service_id__createstamp | 4 | const | 294272 | Using where | +----+-------------+--------+------+------------------------------------------+----------------------+---------+-------+--------+-------------+ -
MySQL 5.7のパラメータの調整(バッファプール調整な ど) 恥ずかしながら MySQL 5.1 & MyISAM 脳でほとんどInnoDB運用の知見がないため、バッフ ァプールサイズなど何が最適なのかの知見が無く、
いろいろ調査して以下のものに行き着きました。 いろいろと調査していたが決め手に欠けていたが、よさげなツールを発見 MySQLTuner https://github.com/major/MySQLTuner-perl