2015年11月12日木曜日

MySQL 5.7のmysql_upgradeは本当にDATETIME型を新しいフォーマットに直してくれるけれど

Upgrading Directly from MySQL 5.0 to 5.7 using an ‘In Place’ Upgrade | MySQL Server Blog を読んでふと思い立ったので。

MySQL 5.7のmysql_upgradeは古いDATETIME, TIME, TIMESTAMPを新しいDATETIME2, TIME2, TIMESTAMP2に変換してくれるからmysqldumpしてからリストアしなくてもいいんだぜ! っていうのが趣旨らしい。それは素敵だ。

↓これの12番目
日々の覚書: あなたのMySQL 5.6トレンド力をチェックする15の質問


ざっと見、確かにやってくれてる。worldデータベースを ダウンロード してきて食わせてみた。
(そういえば、昔はworldはMyISAMで、InnoDB版のworldが別にあったんだけど、今はたぶんInnoDBのだけなんだろうね。1つしかない)

$ cd /usr/mysql/5.5.46/
$ ./scripts/mysql_install_db --datadir=/home/yoku0825/test_55/
$ bin/mysqld_safe --no-defaults --datadir=/home/yoku0825/test_55 &
$ bin/mysql -uroot < ~/world_innodb.sql
$ bin/mysqladmin -uroot shutdown

$ cd /usr/mysql/5.7.9
$ bin/mysqld_safe --no-defaults --datadir=/home/yoku0825/test_55 &
$ bin/mysql_upgrade
Checking if update is needed.
Checking server version.
Running queries to upgrade MySQL server.
Checking system database.
mysql.columns_priv                                 OK
mysql.db                                           OK
mysql.engine_cost                                  OK
mysql.event                                        OK
mysql.func                                         OK
mysql.general_log                                  OK
mysql.gtid_executed                                OK
mysql.help_category                                OK
mysql.help_keyword                                 OK
mysql.help_relation                                OK
mysql.help_topic                                   OK
mysql.host                                         OK
mysql.innodb_index_stats                           OK
mysql.innodb_table_stats                           OK
mysql.ndb_binlog_index                             OK
mysql.plugin                                       OK
mysql.proc                                         OK
mysql.procs_priv                                   OK
mysql.proxies_priv
error    : Table upgrade required. Please do "REPAIR TABLE `proxies_priv`" or dump/reload to fix it!
mysql.server_cost                                  OK
mysql.servers                                      OK
mysql.slave_master_info                            OK
mysql.slave_relay_log_info                         OK
mysql.slave_worker_info                            OK
mysql.slow_log                                     OK
mysql.tables_priv                                  OK
mysql.time_zone                                    OK
mysql.time_zone_leap_second                        OK
mysql.time_zone_name                               OK
mysql.time_zone_transition                         OK
mysql.time_zone_transition_type                    OK
mysql.user                                         OK

Repairing tables
mysql.proxies_priv
Note     : TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format.
status   : OK
Upgrading the sys schema.
Checking databases.
sys.sys_config                                     OK
world.City                                         OK
world.Country                                      OK
world.CountryLanguage                              OK

Repairing tables
mysql.proxies_priv                                 OK
Upgrade process completed successfully.
Checking if update is needed.

mysqlcheck --check-upgrade の後に、引っかかったやつに対してREPAIR TABLEしてくれている様子。


ちなみにデータディレクトリを作り直して5.6だと、

$ cd /usr/mysql/5.6.27
$ bin/mysqld_safe --no-defaults --datadir=/home/yoku0825/test_55 &
$ bin/mysql_upgrade
Looking for 'mysql' as: bin/mysql
Looking for 'mysqlcheck' as: bin/mysqlcheck
Running 'mysqlcheck with default connection arguments
Running 'mysqlcheck with default connection arguments
mysql.columns_priv                                 OK
mysql.db                                           OK
mysql.event                                        OK
mysql.func                                         OK
mysql.general_log                                  OK
mysql.help_category                                OK
mysql.help_keyword                                 OK
mysql.help_relation                                OK
mysql.help_topic                                   OK
mysql.host                                         OK
mysql.ndb_binlog_index                             OK
mysql.plugin                                       OK
mysql.proc                                         OK
mysql.procs_priv                                   OK
mysql.proxies_priv                                 OK
mysql.servers                                      OK
mysql.slow_log                                     OK
mysql.tables_priv                                  OK
mysql.time_zone                                    OK
mysql.time_zone_leap_second                        OK
mysql.time_zone_name                               OK
mysql.time_zone_transition                         OK
mysql.time_zone_transition_type                    OK
mysql.user                                         OK
Running 'mysql_fix_privilege_tables'...
Running 'mysqlcheck with default connection arguments
Running 'mysqlcheck with default connection arguments
world.City                                         OK
world.Country                                      OK
world.CountryLanguage                              OK
OK

mysql_upgrade(というか 中身でやっぱりmysqlcheck --check-upgradeを呼んでる のでどちらかというとmysqlcheck)がそもそも警告すらしてくれない。

でも直すと直る。

mysql> ALTER TABLE mysql.proxies_priv FORCE;
Query OK, 2 rows affected, 1 warning (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 1

mysql> show warnings;
+-------+------+-------------------------------------------------------------------------------------+
| Level | Code | Message                                                                             |
+-------+------+-------------------------------------------------------------------------------------+
| Note  | 1880 | TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format. |
+-------+------+-------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

直るということは、その前までは旧TIMESTAMP型だったんだろうということは想像がつく。

で、取り敢えずはMySQL 5.6でできなかったことをできるようになってて5.7すごい! って言えばいいんだけど、実際に問題になるのはここではなくて、


日々の覚書: MySQL 5.6への移行でmysqldumpを使わなかったらどうなるか

( ´-`).oO(前半部分が盛大に間違っているという残念なエントリーだけどこれの2番目。


===ほぼ引用===
((マスターはmysql_upgradeでアップグレード && スレーブはmysqldumpからリストア) || (マスターはmysqldumpでアップグレード && スレーブはmysql_upgradeでアップグレード)) && (バイナリーログがROWモードで記録された) 場合に、マスターで記録された型情報とスレーブで再生されようとする型情報に不整合が発生するので、

mysql56> SHOW SLAVE STATUS\G
..
    Last_SQL_Errno: 1677
    Last_SQL_Error: Column 0 of table 'd1.t2' cannot be converted from type 'datetime' to type 'datetime'
..

こんな訳のわからない(datetime型からdatetime型への変換に失敗した)エラーでSQLスレッドが転ける。STATEMENTモードでは影響を受けないが、binlog_format= MIXEDでROWモードにフォールバックするようなクエリーが流れているとこれの直撃を食らう。
===ここまで===

なので、マスターが旧DATETIMEでスレーブが旧DATETIMEで、絶対にmysqldumpとかしないと言い切れるなら(非推奨なことを除けば、だけど、10年も前に非推奨になったold_passwordsがこの前まで生きてたんだから、そういう世界線なんだここは)RBRのエラーも起こらないはずなので構わないといえば構わない。

どちらかというと「マスターが5.5でスレーブが5.6以降」だと、CREATE TABLEで新しくテーブルを作った時にもマスターでは旧DATETIME型、スレーブでは新DATETIME型になってこれを踏むことになる。これはmysql_upgradeを使ったインプレースアップグレードだったか、mysqldumpを使ったダンプアップグレードだったかは 関係ない ので、5.5と5.6の間をまたぐレプリケーションはそう長く運用しない方がいい。

スレーブ作り直すの大変だ った と思うよ。

tomcatを再起動せずにlong_query_timeの変更を反映させられないかの思考実験

なんか作ろうと思っていて、その考えてる過程を整理のためにメモ。
取り敢えず目の前にある事案を想定してtomcat, long_query_timeだけど、コネクション永続化しててセッション変数が実効パラメーターなグローバル変数の変更は全部一緒。

どうでもいいですがマークダウンがただのテキストとして書かれてるのは仕様です(このあと社内のドキュメントにコピううんなんでもない)


## 前提

1. `SET GLOBAL long_query_time= n`は@@grobal.long_query_timeの値を書き換える

2. 各スレッドの実効パラメーターは @@session.long_query_time であり、 @@global.long_query_time は @@session.long_query_timeのデフォルト値である

3. よって、既に作成されてしまったスレッド= コネクションに対しては影響を持たない

4. スレッドを再作成するため、tomcatを再起動する必要がある

5. tomcat再起動する(or してもらう)のがめんどい


## 考えたこと

pt-kill を使って、`pt-kill S=/usr/mysql/5.7.9/data/mysql.sock,u=root --idle-time=1 --victims=oldest --wait-after-kill=30s --kill --print --match-command=Sleep` とかやれば古いやつから順番にゆっくり切って再接続をアプリケーションに任せられるかなと思ったけど

  * pt-killを開始した時間以降に接続してきたスレッドは除外対象にしないといけない

    * pt-killを開始した時間以前のスレッドが全滅したら自然に止まってほしい

  * pt-killではクエリーレベルまでしか見てくれないので、トランザクションが走ってるかどうかまでは検知してくれない

    * 迂闊にkillして大量ロールバックされても面倒


## というわけで

* `SELECT MAX(id) FROM information_schema.processlist`で、「開始時点より古いプロセスIDの最大値」を取る

  * プロセスIDは単調増加なので、これよりも大きいプロセスIDを持つスレッドはkillしなくていい

* `SELECT * FROM processlist LEFT JOIN innodb_trx ON processlist.id = innodb_trx.trx_mysql_thread_id WHERE id <= $maxid AND command = 'Sleep' AND time > 3 AND trx_id IS NULL ORDER BY processlist.id LIMIT 1` でスリープしててトランザクション中じゃないいちばん古いプロセスを引いてkill

  * time > 3にしてるのは、0だとMyISAMな複数ステートメント処理(似非トランザクション)のスキマに挟まるかもとか思った

    * いやどんな条件を付けようと、トランザクション非対応な複数ステートメント処理は救えないんだけど一応。。

  * SELECTからkillまでの100ミリ秒くらいの間に開始されたトランザクションはあきらめる(ロールバックが暴走することはないはず)

    * アプリケーションがエラーハンドルしてくれるのが大前提

* ちょっとスリープする

* `SELECT MIN(id) FROM information_schema.processlist WHERE id <= $maxid`がNULLになるまでこれを繰り返す

* なんてことをprogress出しながらやる


どうだろう。
監視のための永続コネクションも検知されたので、user, hostでフィルターはかけるとしてこれじゃダメかしら(そこまでしてtomcatを再起動しちゃダメな理由も見当たらないが)

2015年11月4日水曜日

日本MySQLユーザ会会15周年記念パーティーがありましたよ

去る 10/30(金)、日本MySQLユーザ会の15周年記念パーティーがありました。



ハッシュタグだけまとめましたが、他にハッシュタグなしで面白いこと言ってた人がいらっしゃいましたら是非ともセルフサービスで更新をお願いします :)



smallpalaceさん のブログ MyNA会20151030にいってきた - smallpalace's blog とだいぶカブるんですけど、つらつらと感想など。



お手伝いとして当日「18時に来てね!」と言われているも、18時に行ったら既に椅子は並んでるわ机は揃ってるわ🍺は置いてあるわオードブルも置いてあるわ。
正直、受付のお手伝いをしていた @dupont_kedama さん *以外* は全く役に立ってなかったんじゃないでしょうかお手伝い陣。コロプラさんありがとうございました。

( ´-`).oO(コロプラさんは エンジーニャ募集中らしいよ ってじっちゃが言ってた(2015/10/30現在)


発表者ーズ

@tmtms さん




"ちなみに日本語EUCのcharset名はujisにしと いたで」 正直、スマンカッタ"


木下さん


このあたりから既に酔っぱらって記憶にないものの(何か木下さんに絡んでいた記憶だけはある。。)



"金曜日はMyNA会だからそれまでに終わらせとかないとなと思って"
"木下さんがMySQL Clusterとか言ってるとなんか新鮮"



木下さん的 ○racleへの就職方法。



InnoDB以外の木下さんの偉業(?)



なんかかっこいい。


かじやまさん




なお 奥野さん は "元Sun => MySQL AB => Sunに買収"の時にさすがにこっぴどく怒られたとかなんとか。



長かった。。どこかに全文掲載されたりしないだろうかw



JPACあたりのCommunity Team ManagerのLenkaさんからビデオレターが来てました。

6.xとか7.xとかMySQL Server 2010とか、ホテル「ドルフィン」とか、黒い人に後ろから刺されないかしら大丈夫かしらという感じのネタが続きました。笑ったー。


わたし

正直しゃべったことよく憶えてないんですが、

* MyNAのMLもYahoo知恵袋の代わりくらいには使えるんじゃないか(我ながらひどい。。)
* 最近の主なお仕事は、ビデオレターもくれたLenkaちゃんにMyNAの開催を知らせる簡単なお仕事
* Category: Japanese Documentationのばぐれぽは梅ッシュ(インド人? だったかな?)がVerifyしてくれて誰かさん(アジア人で日本語が上手い)が修正してくれる MySQL Bugs: #77306: Misprint in example storage engine
* MontyはX-Filesに出てきそうな顔

まいんだーさん






前にまいんだーさんから「詳しい人がカジュアルに難しい話をできる場」と聞いたことがあります。




そのあと堤井さんに連れられて10人弱で飲みに行ったんですけど、夜の赤坂は怖かった。
夜行バスを逃したとみたさんに「じゃあまた5年後に」と言われてお店を後にしました。またMyNA会で会いましょう :)