読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近は統計とAnsibleをさわりはじめたお(^ω^ = ^ω^)

MySQLで破損していたテーブルを復旧した件

MySQL MySQL5.7 WordPress

WordPressにログインしようとアクセスしたら、摩訶不思議エラーが発生。と、会社の人たちから連絡。

mysql_query() unable to save result set

↑のエラーで検索すると、よくあるのはMySQLからの結果をPHPが受け取れないエラーが多いらしいが、今回はそうじゃないっぽい・・・?

windowsos -> macosへデータ移行

エラーが発生したのはWindowsOSでした。コマンドラインでの復旧方法しか知らなかったので、mysqlのデータベースディレクトリをコピーしてmacへ送信。

mac側のmysqlディレクトリに追加して、mysqlコマンドラインで確認してみました。

macのosやmysqlのバージョンはこちら

$ sw_vers
ProductName:  Mac OS X
ProductVersion: 10.11.5
BuildVersion: 15F34

$ mysql -u root -p -D mysql -e "select version()"
Enter password: 
+-----------+
| version() |
+-----------+
| 5.7.13    |
+-----------+

-- wordpressは壊れたテーブルがあるデータベース名
$ show table status from wordpress
-- 色々省略したけど、table型はMyISAMでした
$ sudo cd /usr/local/var/mysql/
$ sudo unzip ~/Downloads/wordpress.zip
$ chown -R _mysql:_mysql wordpress

これで配置はおk

check table コマンド

check tableのコマンドは、複数テーブルのエラーがないかどうかをチェックするコマンドです。

また、table型によっては使えるオプションと使えないオプションがあるっぽいね

意味
QUICK 正しくないリンクをチェックするための行のスキャンを行いません。InnoDB および MyISAM テーブルとビューに適用されます。
FAST 正しく閉じられていないテーブルのみを検査します。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。
CHANGED 最後のチェック以降に変更されたか、または正しく閉じられていないテーブルのみをチェックします。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。
MEDIUM 削除されたリンクが有効であることを検証するために行をスキャンします。また、行のキーチェックサムも計算し、キーの計算されたチェックサムを使用してこれを検証します。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。
EXTENDED 行ごとにすべてのキーの完全なキールックアップを実行します。これにより、テーブルの 100% の整合性が保証されますが、長い時間がかかります。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。

今回はMEDIUMを使いました。

オプションについての利用用途はまだよくわかっていませんが、検索したらなんかMEDIUM使っている人多かったので。。。

http://www.freeml.com/bl/6236480/84512/

とりあえずデータベースにログインしてから実行してみる。

mysql> check table wp_options medium;
+----------------------+-------+----------+-----------------------------------------------------------+
| Table                | Op    | Msg_type | Msg_text                                                  |
+----------------------+-------+----------+-----------------------------------------------------------+
| wordpress.wp_options | check | warning  | Table is marked as crashed                                |
| wordpress.wp_options | check | warning  | 10 clients are using or haven't closed the table properly |
| wordpress.wp_options | check | error    | Found 175 keys of 174                                     |
| wordpress.wp_options | check | error    | Corrupt                                                   |
+----------------------+-------+----------+-----------------------------------------------------------+
4 rows in set (0.00 sec)

うぬぬ。。。やっぱりなんかぶっ壊れているっぽいぞ。

repair table コマンド

repair tableコマンドは特定のステレートエンジンに対してのみ、破損している可能性のあるテーブルを修復してくれるとのこと。

InnoDBは対応していないっぽい。。。。。個人的にはそっちを多く使うんですけど。。。

オプションが色々ありますが、USE_FRMを使いました。

USE_FRM オプションは、.MYI インデックスファイルがない場合や、そのヘッダーが破損している場合に使用できます。このオプションは MySQL に、.MYI ファイルヘッダー内の情報を信頼せずに、.frm ファイルからの情報を使用してファイルヘッダーを再作成するよう指示します。この種類の修復は、myisamchk では実行できません。

https://dev.mysql.com/doc/refman/5.6/ja/repair-table.html

mysql> repair table wp_options USE_FRM;
+----------------------+--------+----------+------------------------------------------------------+
| Table                | Op     | Msg_type | Msg_text                                             |
+----------------------+--------+----------+------------------------------------------------------+
| wordpress.wp_options | repair | info     | Delete link points outside datafile at 349632        |
| wordpress.wp_options | repair | info     | Delete link points outside datafile at 423104        |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 424072  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 424176  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 424724  |
| wordpress.wp_options | repair | info     | Delete link points outside datafile at 436636        |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 436744  |
| wordpress.wp_options | repair | info     | Found block with too small length at 437668; Skipped |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 437980  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 438052  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 438236  |
| wordpress.wp_options | repair | warning  | Number of rows changed from 0 to 173                 |
| wordpress.wp_options | repair | status   | OK                                                   |
+----------------------+--------+----------+------------------------------------------------------+
13 rows in set (0.04 sec)

おおー。

もっかいcheck tableを実行してみる。

mysql> check table wp_options medium;
+----------------------+-------+----------+----------+
| Table                | Op    | Msg_type | Msg_text |
+----------------------+-------+----------+----------+
| wordpress.wp_options | check | status   | OK       |
+----------------------+-------+----------+----------+
1 row in set (0.01 sec)

おおぉー!

これでよし。

この流れを全テーブルに実行してみました。

特定のファイルが見つからなくて、repairできなかった時

1つだけおかしなテーブルが。。。

mysql> check table wp_usermeta medium;
+-----------------------+-------+----------+----------------------------------------------------------+
| Table                 | Op    | Msg_type | Msg_text                                                 |
+-----------------------+-------+----------+----------------------------------------------------------+
| wordpress.wp_usermeta | check | warning  | 9 clients are using or haven't closed the table properly |
| wordpress.wp_usermeta | check | status   | OK                                                       |
+-----------------------+-------+----------+----------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> repair table wp_usermeta USE_FRM;
+-----------------------+--------+----------+------------------+
| Table                 | Op     | Msg_type | Msg_text         |
+-----------------------+--------+----------+------------------+
| wordpress.wp_usermeta | repair | Warning  | Can't open table |
| wordpress.wp_usermeta | repair | status   | Operation failed |
+-----------------------+--------+----------+------------------+
2 rows in set (0.00 sec)

mysql> repair table wp_usermeta USE_FRM;
+-------------+--------+----------+----------------------------------------+
| Table       | Op     | Msg_type | Msg_text                               |
+-------------+--------+----------+----------------------------------------+
| wp_usermeta | repair | error    | Failed generating table from .frm file |
+-------------+--------+----------+----------------------------------------+
1 row in set, 2 warnings (0.01 sec)

なおんぇええええ!!!

しかもなぜかエラーの返事もかわった(´;ω;`)ブワッ

怖い

でもメッセージみたら、「.frmがないお」みたいなエラーですね。

そんなばかな。

シェルのコンソールに戻り、ファイルを確認してみる。

$ sudo ls -l wp_usermeta*
-rw-r--r--  1 _mysql  _mysql  3656  7 22 10:02 wp_usermeta.MYD-81bc_16
-rw-r--r--  1 _mysql  _mysql  9216  7 21 22:49 wp_usermeta.MYI
-rw-r--r--  1 _mysql  _mysql  8684  7 22 09:55 wp_usermeta.frm

え・・・・?

wp_usermeta.MYD-81bc_16 <= なにこれ?

よくわからないけど、復旧の途中でミスった・・・・?

わからないけど、復旧させてみる。

とりあえず、元に戻す。

$ sudo cp wp_usermeta.MYD-81bc_16 wp_usermeta.MYD
$ sudo chown _mysql:_mysql wp_usermeta.MYD
$ ls -l wp_usermeta*
-rw-r--r--  1 _mysql  _mysql  3656  7 22 10:02 wp_usermeta.MYD
-rw-r--r--  1 _mysql  _mysql  3656  7 22 10:02 wp_usermeta.MYD-81bc_16
-rw-r--r--  1 _mysql  _mysql  9216  7 21 22:49 wp_usermeta.MYI
-rw-r--r--  1 _mysql  _mysql  8684  7 22 09:55 wp_usermeta.frm

うし。

んで、念のため一旦mysqlを再起動。

$ sudo mysql.server restart

次にmysqlにログインして、もう一度checkrepairを実行。

mysql> check table wp_usermeta medium;
+-----------------------+-------+----------+----------------------------------------------------------+
| Table                 | Op    | Msg_type | Msg_text                                                 |
+-----------------------+-------+----------+----------------------------------------------------------+
| wordpress.wp_usermeta | check | warning  | 9 clients are using or haven't closed the table properly |
| wordpress.wp_usermeta | check | status   | OK                                                       |
+-----------------------+-------+----------+----------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> repair table wp_usermeta USE_FRM;
+-----------------------+--------+----------+-------------------------------------+
| Table                 | Op     | Msg_type | Msg_text                            |
+-----------------------+--------+----------+-------------------------------------+
| wordpress.wp_usermeta | repair | warning  | Number of rows changed from 0 to 23 |
| wordpress.wp_usermeta | repair | status   | OK                                  |
+-----------------------+--------+----------+-------------------------------------+
2 rows in set (0.01 sec)

mysql> check table wp_usermeta medium;
+-----------------------+-------+----------+----------+
| Table                 | Op    | Msg_type | Msg_text |
+-----------------------+-------+----------+----------+
| wordpress.wp_usermeta | check | status   | OK       |
+-----------------------+-------+----------+----------+
1 row in set (0.00 sec)mysql>

エラーメッセージが変わってます! そして復旧もできたっぽい!

ここまでできたら、あとはsqldump取得して、windows osの方へデータを送って、importしてもらって復旧できました。

まとめ

できたのはいいけど、オプションの意味がまだよくわかっていないので、これから調べてみる。

目標ログ日記15

その他

本日は

家族サービス => 畑でいたずらして野菜げと! => 昼ごはん前に運動 => 後輩におそそわけ => 本屋を2店舗うろうろ => 家族サービス => 夕飯を家で食べる => そして今

なんか疲れた。が、ほのぼのしてていい感じ。

運動

今週はそんなに走っていない気がする(多分3〜4日ぐらい)

  • ジョギング 3km
  • 腹筋ローラー 10回 x2
  • 腹筋 15回 x2
  • サイドクランチ 30回 x2
  • 腕立て伏せ 15回 x2
  • スクワット 25回

スクワットのセットを1つにしている。足が痛いので。。。

ちなみに1kg減ったお(^ω^

(只今74kgだがな。。。)

読書

  • 「コーディングを支える技術」をちょこちょこ読んでいます。

IT

  • CakePHP3でつまづき中。ええ本ないかね。

英語

本を買おうかなとおもったけど、やっぱりやめた。(お金がなry)

今週良かったこと

  • なんか運動のハードルが減った。とりあえず走るのが楽になってきた。汗はむっちゃかくけど。

今週の反省

  • 仕事の漏れが多く、あんまり良くない。チェックの意識をアップ。
  • 大きく残業してしまった。もう少し仕事のスピードをあげたいわ
  • 本をあんましよんでねぇえええええええええええええ
  • あれな同人誌をWebで探すの禁止したい。ほんま時間がもったいないお!

今後

今後。というより感想。

うれしいことがありました。

けど、そのことについて応えることができませんでした。。。orz (なんのことかわからないはずですが、本当ショック)

ちょっと今の現状をサボったことが原因ですなー。

自分ひとりだけレベルアップじゃなくて、人の成長を促す&手伝うようにしなければならないかも。

ただ、教えるにはわかっていないといけないはずなので、引き続きレベルアップしていこうと思う。

目標ログ日記14

その他

色々ペースが遅くなった。

運動

まぁいいペースじゃね?

毎日続けられればいいかなー?と思っていたけど、やっぱり残業とかもあるので、てきとうな気持ちで続けています。

今日もこれ書き終わったらジョギングしにいくお(^ω^

  • ジョギング 3km
  • 腹筋ローラー 10回 x2
  • 腹筋 15回 x2
  • サイドクランチ 30回 x2
  • 腕立て伏せ 15回 x2
  • スクワット 25回 x2

読書

  • 「嫌われる勇気」は読み終わりました!
  • CODE COMPLETE 上
    • 全然読み進めていない(´・ω・`)
  • 「コーディングを支える技術」を買った

  • Pythonによるデータ分析入門」も買った

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

なんか他の業界の知見系が足りない気がする。。。

IT

  • CakePHP3をプライベートで試しているお!
    • やっぱりなれないうちは大変。。。
  • AngularJS楽しくなってきました
    • component指向がいまいち見えていないけどねorz

英語

検索はほとんど英語になりました。

「how can i do 〜」(俺はどうすればいい?〜)

「〜 not working」(〜が動かんよ!)

みたいな感じで検索すると捗る。(検索した結果も英語なので全部は読めませんが)

単語力が大事!って話も聞いたことがあるので、単語を覚える週間を手に入れなければいけないのでは?と思っている。

今週良かったこと

  • プログラミングで色々挑戦するプロジェクトが増えた(ほとんど会社”外”なのがあれだけど)。いっぱい経験してやるぜ!

今週の反省

  • お金を貯める習慣がほぼ失われつつある。浪費を防ぎたい
    • 本買い過ぎ。まずは今ある本を読んでから他のを買いたい
    • 遊びすぎ。来月は勉強会も含め月3回に抑えたい

今後

じゃあその課題について、どう動けば良いか。

  • 本買い過ぎ。まずは今ある本を読んでから他のを買いたい
  • 遊びすぎ。来月は勉強会も含め月3回に抑えたい

【CakePHP3】ViewでRouterクラスを使うにはuseを使って呼び出さないといけない

CakePHP PHP CakePHP3.x

CakePHP3を使って、CakePHP2みたいに普通にコーディングしていると。。。

Router::url in view generates fatal error: class not found

え? まじ? クラスなくなったんかないな。」と驚いて検索したところ。

github.com

You are missing a use statement. Because CakePHP 3.0 uses namespaces, you have to either use the fully namespaced classname Cake\Routing\Router or add use Cake\Routing\Router to the top of your view file.

なんと! viewでもnamespaceを使ってロードしなければいけないのか。

<?php
use Cake\Routing\Router;
?>
<a rel="button" class="submit btn btn-success" href="<?= Router::url(['controller' => 'Users', 'action' => 'index']) ?>">

つーことで、使うにはこうしなければならないので注意。

【AngularJS1.5.x】directiveのtemplateにfilterを引数で渡したい

AngularJS AngularJS1.5.x JavaScript

渡したかった。

  • index.html
<first-directive main="main.myDirective" filter-name="number"></first-directive>
  • app.js
    .directive('firstDirective', ['$log', 'FigureService', function ($log, FigureService) {
        return {
            restrict: 'E',
            scope: {
                directiveMain: '=main',
                filterName: '=filterName'
            },
            controller: 'Main',
            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li>{{directiveMain.circle | filterName}}</li>' +
                      '</ul>',
            link: function(scope, element, attrs, controller) {
            }
        }
    }])

エラーでした。

Error: $injector:unpr Unknown Provider

Unknown provider: filterNameFilterProvider <- filterNameFilter

うーむ。filterとして認識されていない?

            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li>{{directiveMain.circle | filter:filterName}}</li>' +
                      '</ul>',

filter:っていう文字を追加

Error: filter:notarray Not an array

Expected array but received: 314.1592653589793

「配列希望だけど、違うよ」って感じ。何故だ。

次は普通に使ってみる

                      '    <li>{{directiveMain.circle | number}}</li>' +

これは動いた。

うーむ。。。

30分経過

だんだん英語の記事の引っぱりかたがわかってきた。

「angularjs filter argument」とかで検索してしまうと、「angularjsのfilterで引数の渡し方」みたいな記事しか引っぱってこない。

「how can i ~」とか「how to ~」とかつけると、「やり方」=> 手順っぽい記事を探してくれる。

「how to pass filter to a directive」とかで検索するとマッチした。(+ in angularjs とか書くと完璧かも)

stackoverflow.com

で、directivescopeで渡したいfilterは、templateで実行することができないっぽい。

実現できた書き方としてこんな感じ。

    .directive('firstDirective', ['$log', 'FigureService', '$filter', function ($log, FigureService, $filter) {
        return {
            restrict: 'E',
            scope: {
                directiveMain: '=main',
                filterName: '=filterName'
            },
            controller: 'Main',
            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li><input type="text" ng-model="directiveMain.trapezoid" ng-blur="myBlur()" ng-model-options="{updateOn: \'blur\'}"></li>' +
                      '</ul>',
            link: function(scope, element, attrs, controller) {
                // directiveがインスタンス生成される度に実行される
                $log.info(scope);
                $log.info(element);
                $log.info(attrs);
                $log.info(controller);

                // Serviceを仕様して、directiveのscopeを変更
                // controllerとbindするとmodelがシェアされる
                scope.directiveMain.triangle = FigureService.triangle(10, 5);
                scope.directiveMain.circle = FigureService.circle(10);
                scope.directiveMain.trapezoid = $filter(scope.filterName)(FigureService.trapezoid(1320, 5, 3)); // ここの部分

                scope.myBlur = function() {
                    console.log($filter(scope.filterName)(scope.directiveMain.trapezoid));
                };
            }

linkで実行すれば良い。

だがしかし、これだと初回の実行だけで、値を変えた場合はfilterが実行されない。

なので、常に実行する場合はeventの発火を監視して、filterを実行すればいいんじゃないかなと思う。