GA

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/04

日本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会で会いましょう :)

2015/10/19

MySQL 5.7.9でSHUTDOWN *ステートメント* が実装されたよ!

MySQL :: MySQL 5.7 Reference Manual :: 13.7.6.7 SHUTDOWN Syntax

まあ`mysqladmin shutdown`にしたって mysql_shutdown関数 を叩いて COM_SHUTDOWNパケット を送っているだけで、COM_SHUTDOWNはmysqld側のパーサー(sql/sql_parse.cc)が権限とかよしなに判定して終了処理を呼び出しているので、SQLからできたからってそこまで違うことではない。権限もちゃんとShutdown_Privが無ければ権限不足のエラーが返るので、SQLインジェクション= 即死という訳でもない。

が、単純に( ゚д゚) ファッ!? ってなる。


mysql> SHUTDOWN -- コマンドではなくSQLステートメントなので、";"で終端しないといけない。
    -> ;
Query OK, 0 rows affected (0.00 sec)

`FLUSH TABLES WITH READ LOCK`した端末でそのままシャットダウンできるのはいいのかも知れないけどね。。

MySQL 5.7のinnodb_default_row_format 影響範囲まとめ

日々の覚書: MySQL 5.7.9のinnodb_default_row_formatがまた何か企んでいるようです ではまだ5.7.9が手元になかったので推測でしたが、公開されたので試してみたまとめ。

|PRIMARY KEY|ALTER            |変換|メモ                                          |
|-----------|-----------------|----|----------------------------------------------|
|あり,なし  |ADD COLUMN       |Yes |                                              |
|あり,なし  |DROP COLUMN      |Yes |                                              |
|あり,なし  |ADD FOREIGN KEY  |Yes |                                              |
|あり,なし  |ADD KEY          |No  |ALGORITHM= INPLACE                            |
|あり,なし  |ADD KEY          |Yes |ALGORITHM= COPY                               |
|なし       |ADD PRIMARY KEY  |Yes |                                              |
|あり       |DROP PRIMARY KEY |Yes |                                              |
|あり,なし  |ADD UNIQUE KEY   |No  |                                              |
|あり,なし  |MODIFY, CHANGE   |No  |int => int(カラムリネームのみ)                |
|あり,なし  |MODIFY, CHANGE   |No  |varchar(32) => varchar(32)(カラムリネームのみ)|
|あり,なし  |MODIFY, CHANGE   |No  |varchar(32) => varchar(64)(latin1)            |
|あり,なし  |MODIFY, CHANGE   |Yes |varchar(32) => varchar(256)(latin1)           |
|あり,なし  |MODIFY, CHANGE   |Yes |int => bigint                                 |
|あり,なし  |MODIFY, CHANGE   |Yes |int => int unsigned                           |
|あり,なし  |MODIFY, CHANGE   |Yes |int => varchar(32)                            |
|あり,なし  |Engine= InnoDB   |Yes |OPTIMIZE TABLE                                |
|あり,なし  |ALTER SET DEFAULT|No  |                                              |
|あり,なし  |RENAME           |No  |テーブル名のリネーム                          |



メタデータだけをゴニョる場合(テーブルリネーム、カラムリネーム、デフォルト値の変更)と、ADD KEY(FOREIGN KEY, FULLTEXT KEYはダメ。SPACIALは試してない)だけが暗黙のROW_FORMAT変換が走らない。それ以外は走る。

しかしPKなしのUNIQUE KEY追加ってそれがクラスターキーになるんだけどROW_FORMAT変換は走らないのね。。


テストコードはこちら。mtrスタイルだけどステートメントを上から全部順番に実行すればフツーのmysqlでもいける。

https://gist.github.com/yoku0825/57ba8a8788b792e0ca39


実際、ROW_FORMATの変換によりどの程度の負荷が発生するのやら、簡単なベンチを取ってみる。


mysql> CREATE TABLE t1 (num serial, val varchar(32));
mysql> LOAD DATA INFILE '/var/lib/mysql-files/md5' INTO TABLE t1; -- 容量があんまりなかったので10万件ほど突っ込む

$ while true ; do mysql -e "INSERT INTO d1.t1 (val) VALUES ('dummy')"; done

mysql> ALTER TABLE t1 MODIFY val varchar(64); -- 暗黙のROW_FORMAT変換は走らない
mysql> ALTER TABLE t1 MODIFY val varchar(256); -- 暗黙のROW_FORMAT変換が走る




ちょっとズレがあるけど、ALTER TABLEは変換なしが横軸17のあたり、変換ありが横軸14のあたり(あ、縦軸の単位はbytesです)

変換なしのALTERは10msくらい、変換ありのALTERは100msくらい。rebuild_write(単位はbytes)がハネてるので、やっぱりオンラインはオンラインでもROW_FORMAT変換が走っちゃうと本番ではそれなりに行きそう。


本番では pt-online-schema-change 使ってるからあんま関係なさそうですなんですけどね ;)

MySQLのsysスキーマまとめ

MySQL 5.7で標準バンドルされるsysスキーマ。その実態はperformance_schemaやinformation_schemaから「それっぽい」情報を集めているview。

5.7の機能っぽく語られるけど、前身は ps_helper でMySQL 5.5から使える(けど、5.5のperformance_schemaは情報が少なすぎて役に立つ気配がしない。オーバーヘッドもでかいし)

* MySQL 5.7ではperformance_schemaもだいぶオーバーヘッド落ち着いてきたみたいだし、デフォルトのまま取り敢えず有効にしておいた方がいい。ウチはMySQL 5.6から有効にしてる。
* CPUバウンドの場合確かにオーバーヘッドが見えるけど、I/Oネックになる場合は全然気にならない程度のオーバーヘッドだから、自信がある時だけOFFにする方がいいと思う。
* performance_schema.setup_actorsをTRUNCATEしておけば、新規接続コネクションはトラッキングOFFになるのでそれを活用するのもアリ。
* 5.6で使うには↓のやり方。

$ git clone https://github.com/MarkLeith/mysql-sys.git
$ cd mysql-sys
$ mysql -uroot -p < ./sys_56.sql


## sysスキーマでオススメのView

### sys.metrics
* 一通り監視したくなりそうなやつをSELECTだけでアクセスできるようになってるView
* こんなスクリプト で黙ってfluent_loggerで食わせるだけでKibanaのグラフが出来る。素敵。

### sys.schema_index_statistics
* どのインデックスがどの程度呼ばれていて、どの程度のレスポンスタイムなのかを見られる

### sys.schema_unused_indexes
* schema_index_statisticsの応用で、一度も呼ばれてないインデックスをリストしてくれる

### sys.statement_analysis
* リアルタイムpt-query-digestっぽい感じ。
* performance_schema..events_statements_summary_by_diges t.digest_textとJOINしないとクエリーの完全なステートメントが見えない(勝手に切り詰められている)
* 前に書いた 日々の覚書: MySQLのperformance_schemaでどれくらいの情報が見られるのか のevents_statements_summary_by_digest のView

### sys.statements_with_errors_or_warnings
* これ便利。 ワーニングを握りつぶしている悪い子はいねが?
* gtid-enforce-consistency= WARNと組み合わせてGTID有効化前の準備ができる


## sysスキーマでオススメのプロシージャ

### sys.create_synonym_db('base_database', 'synonym_database')
* やってることはCREATE DATABASE synonym_databaseして、SHOW TABLES FROM base_databaseしてテーブル名を引っこ抜いて、CREATE VIEW synonym_databaseで同じ名前のビューを作ってくれるだけ。
  * CALL sys.create_synonym_db('performance_schema', 'ps')ってしておくと、performance_schemaのタイプ数が減ってすごく捗る。今までどうして考え付かなかったのかってくらい。
  * CALL sys.create_synonym_db('informaiton_schema', 'i_s')も捗る。
* 感動したので書いてみた。sysでなきゃできないなんてことはない。

### sys.ps_setup_disable_background_threads
* バックグラウンドスレッドの統計情報を一発でOFFにする。UPDATE performance_schema.threads SET instrumented= 'No' WHERE type= 'BACKGROUND'とほぼ一緒だと思う。
* init-commandが空いてるならこれをCALLしてもいいかも

### sys.ps_setup_enable_thread
* 特定のスレッドのp_sを有効化できる。
* p_s.setup_actorsを空っぽにしておくと、その後接続してきたコネクションのトラッキングがOFFになるので、空っぽにしておいて、使いたくなった時だけ(5.5のSET profiling= 1みたいなノリで)有効にできる。
  * profilingと違って、自分以外のスレッドも有効化できる。
* 引数はSHOW PROCESSLISTのID
  * 自分自身のスレッドを指定する場合、CALL ps_setup_enable_thread(@@pseudo_thread_id); が便利。

### sys.ps_setup_save, ps_setup_reload_saved, ps_setup_reset_to_default
* 現在のperformance_schema.setup_*の中身をperformance_schema.tmp_setup_*テーブルに保管/リストアしてくれる。
*テンポラリーテーブルに保存するので、コネクションを切ると折角保管したtmp_setup_*は失われる*
* ps_setup_saveは引数が必要。タイムアウトまでの秒数。1でいい。
* ps_setup_reload_savedは引数なし。
* ps_setup_reset_to_defaultは0または1の引数。1を指定すると、実行したクエリーを表示してくれる。
* MySQL 5.7.8のps_setup_reset_to_defaultにはバグがあって上手く動かない。5.7.9なら動く。
  * MySQL Bugs: #77927: sys.ps_setup_reset_to_default fails due to ENABLE/HISTORY column in setup_actors

### sys.ps_truncate_all_tables
* 現在までの統計情報(performance_schemaの*summary*と*history*)をクリアする。
* 引数は0または1、1にすると実行されたTRUNCATE文が表示される。


最近作ったMySQL 5.6はperformance_schemaを有効にしてて、結構便利に使ってます。sys。

2015/10/16

MySQLのrootのパスワードを忘れてしまった…やその類似ケースを、mysqldを停止せずに何とかするメモ

MySQLのrootパスワード忘れた、をググると、--skip-grant-tables を有効にして再起動せよ、というのにぶち当たるのが普通なんですが、カジュアルに再起動する訳にいかないことってあるじゃないですか。

そんなときのTIPS。


まず、ダミーのデータディレクトリをmysql_install_dbで作ります。これはrpmで入れた環境なので、/usrはbasedirです。

$ cd /usr
$ bin/mysql_install_db --no-defaults --datadir=/home/mysql/dummy


ここに、パスワードを変えたいMySQLのmysql.userテーブルをコピーします。少なくともMySQL 5.7.8現在、mysql.userはまだMyISAMなのでコピーできます。
rootが使えないはずなのにmysql.userテーブルがゴリゴリ更新されているような環境があるはずはないと信じているので、取り敢えずはシンプルなcpで大丈夫です。

コピーしたらダミーのデータディレクトリを使ってMySQLを起動します。--socketオプションを忘れると本番のソケットファイルが握りつぶされる可能性があるので注意。。

$ cp -ip /var/lib/mysql/mysql/user.MYD /home/mysql/dummy/mysql/user2.MYD
$ cp -ip /var/lib/mysql/mysql/user.MYI /home/mysql/dummy/mysql/user2.MYI
$ cp -ip /var/lib/mysql/mysql/user.frm /home/mysql/dummy/mysql/user2.frm
$ bin/mysqld_safe --no-defaults --datadir=/home/mysql/dummy --port=23000 --socket=/home/mysql/dummy/mysql.sock &
$ bin/mysql -uroot -S/home/mysql/dummy/mysql.sock

mysql> SELECT user, host, password FROM mysql.user2;
+-------------+-----------------+-------------------------------------------+
| user        | host            | password                                  |
+-------------+-----------------+-------------------------------------------+
| root        | localhost       | *........................................ |
| xxxxxxxxx   | localhost       | *........................................ |
| root        | 127.0.0.1       | *........................................ |
| xxxxxxxx    | xxx.xxx.xxx.%   | *........................................ |
| xxxxxxxxxxx | localhost       | *........................................ |
| xxxx        | localhost       | *........................................ |
| xxxxx       | xxx.xxx.xxx.%   | *........................................ |
| xxxxx       | xxx.xxx.xxx.xxx | *........................................ |
+-------------+-----------------+-------------------------------------------+
8 rows in set (0.00 sec)


この通りコピーできたので、UPDATEステートメントでパスワードを書き換えます。

mysql> UPDATE mysql.user2 SET password= PASSWORD('Do_you_love_Perl6?') WHERE (user, host)= ('root', 'localhost');


更新できたらダミー側のMySQLを落とし、落とせない方のMySQLのmysql.userテーブルを上書きします(といってもバックアップは取っておいた方が良かろうかと)


$ bin/mysqladmin -uroot -S/home/mysql/dummy/mysql.sock shutdown
$ cp -ip /home/mysql/dummy/mysql/user2.MYD /var/lib/mysql/mysql/user.MYD
$ cp -ip /home/mysql/dummy/mysql/user2.MYI /var/lib/mysql/mysql/user.MYI

さてこの状態だと、「mysql.userテーブルにUPDATEはかかっているけどFLUSH PRIVILEGESが必要な状態」であり、「でもFLUSH PRIVILEGESするためのrootに接続できない」状態になるかと思います。
そこでkill -HUPですよ奥さん。


$ pkill -HUP mysqld
$ pkill -HUP mysqld

SIGHUPを受け取ると このへんのコード を通って、"FLUSH PRIVILEGES"や"FLUSH HOSTS", "FLUSH LOGS"その他と同じ処理が流れるので、MySQL上のアカウントにアクセスできなくても無事"FLUSH PRIVILEGES"できる。

…コード上通ってそうなのに、何故か2回SIGHUP送らないと反映されない(5.1でも5.6でも5.7でも…なんだろう。同じif文の中のmysql_print_statusはちゃんと呼ばれてエラーログにデバッグ情報吐いてるのに。。)ので取り敢えず2回やっている。深く考えてはいない。


この手段を一番よく使うのはアレですね。
ソケットファイルが何故か消えてて、--skip-name-resolveでroot@localhostはあるけどroot@127.0.0.1がないから--protocol=tcpで逃げられない時に、root@127.0.0.1を作るのに使います。。


【2015/10/16 15:43】



その通りでした! ありがとうございます!!
https://github.com/mysql/mysql-server/blob/5.6/sql/sql_reload.cc#L56-L69