2010-03-22

『売上猫くん on MySQL』開発日記 - 番外3 - 0を書き込みできない

売上明細テーブル( vw_salesdtls)のInt型のフィールド(balanceFlg)に値を書き込もうとする。他の値は書き込みできるのだが、“0”の書き込みが実行できない。 ログで何が起こっているのか確認する。

Commitに失敗している場合はバイナリログには記録されないので、mysqlbinlog は使えない。 そこで、一般ログというものを、

mysql> set global general_log="ON";

で作成してみる。 以下、1を立てて成功したログと、0で失敗したログ(一部抜粋)。

【1立てで成功】
9 Query SELECT ID,`売上番号`,balanceFlg, ~略~ FROM vw_salesdtls WHERE ID=8340 FOR UPDATE
9 Query UPDATE vw_salesdtls SET balanceFlg=1 WHERE ID=8340

【0立てで失敗】
8 Query SELECT ID,`売上番号`,balanceFlg, ~略~ FROM vw_salesdtls WHERE ID=8341

失敗したほうでは、なぜか FOR UPDATE 以下が発行されず、当然これでは更新できない。 当初はInnoDB側に何か問題があるのかと疑ったが、FileMakerが適切なクエリを発行していないことがわかった。 ちなみに、類似した他のテーブルでは、1、0の値に関係なく、更新(Update)は成功する。

いろいろとやってみた。FMのファイルを修復したり、レイアウトモードにして数字の書式を変更してみたり、フィールド定義を眺めてみたり。 そして、これが FileMaker のバグだと判明。 なんと、FileMaker は 空欄(null)→0 への変更は変更と認識しない、null=0 と認識するのである。 更新と認識しないので、 Update が発行されない。 恐ろしい。

結論
ということで、null と 0 を区別して扱う必要がある場合は、非常に注意が必要だ。 0 を参照キーするのは極力避けるべきた。 MySQL側で初期値を0に設定しておく、というのは一案かもしれない。
ちなみに、上述のように「null=0 と認識」するので、0→空欄lに変更を行っても、コミットすると 0 のままである。



関連リンク:『売上猫くん on MySQL』開発日記の記事一覧

2010-03-16

『売上猫くん on MySQL』開発日記 - 番外2 - MySQLミラーサイト

MySQL サイトが今朝から落ちてる。 レファレンスマニュアルが見れない、つまり開発できない。Googleのキャッシュは遅すぎる。 MySQLの全機能を網羅し、信頼の置けるドキュメントはここにしかない(と思う)。「MySQLの開発者はこういうときどうしているのだろう?」等と思いつつ、、、ミラーサイトをみつけた。これタイの大学のサイト。Googleキャッシュよりはずっと早い。 この大学のトップページにはなぜか秋篠宮殿下が…



関連リンク:『売上猫くん on MySQL』開発日記の記事一覧

2010-03-15

『売上猫くん on MySQL』開発日記 - 番外1 - 全データベース削除→リストア

あるサーバにあるデータベースダンプを別のサーバに移動。その後、MySQLのすべてのデータベースを削除し、リストアのテストを行おう思い、まず、

> drop database information_schema
(だったと思う)

を実行してみた。 すると、「information_schemaは削除できない」旨のメッセージが表示される。
その後、mysqlを再起動しようとするとエラーが出て起動しない。 データフォルダをみると、mysqlを含むすべてのデータベースは削除されている。エラーログをチェック(←これ大事)すると、 mysql データベースは起動に必須らしい。そこで、元のサーバから無理やりこのmysql フォルダをコピーし(サーバ停止無、こんなことやっていいいのか?)、丸ごと、起動しなくなった別サーバ内にコピー。 その後は再起動できた(ここまで半日潰れる)。

そこで、

> show databases

を実行すると、やはり表示されるのは、mysql データベースのみ。 そこで、コマンドプロンプトからリストアを実行すると、以下のようなエラーが出る。

InnoDB: Error: table test/parent already exists in InnoDB internal
InnoDB: data dictionary. Have you deleted the .frm file
InnoDB: and not used DROP TABLE? Have you used DROP DATABASE
InnoDB: for InnoDB tables in MySQL version <= 3.23.43? InnoDB: See the Restrictions section of the InnoDB manual. InnoDB: You can drop the orphaned table inside InnoDB by InnoDB: creating an InnoDB table with the same name in another
InnoDB: database and moving the .frm file to the current database.
InnoDB: Then MySQL thinks the table exists, and DROP TABLE will
InnoDB: succeed.

InnoDB内部の記録と不整合があるらしいので、一旦、同名の空のデータベースを作成し、それを削除したあとにもう一度リストアをやってみるとやっと成功。 めでたし、めでたし

参考サイト:トラブルシューティング InnoDB データ ディクショナリ操作



関連リンク:『売上猫くん on MySQL』開発日記の記事一覧