付録 A. 問題と一般的なエラー

目次

A.1. 問題の原因を突き止める方法
A.2. MySQL 使用時によくあるエラー
A.2.1. Access denied エラー
A.2.2. MySQL server has gone away エラー
A.2.3. Can't connect to [local] MySQL server エラー
A.2.4. Client does not support authentication protocol エラー
A.2.5. Host '...' is blocked エラー
A.2.6. Too many connections エラー
A.2.7. Some non-transactional changed tables couldn't be rolled back エラー
A.2.8. Out of memory エラー
A.2.9. Packet too large エラー
A.2.10. 通信エラー/Aborted connection
A.2.11. The table is full エラー
A.2.12. Can't create/write to file エラー
A.2.13. クライアントでの Commands out of sync エラー
A.2.14. Ignoring user エラー
A.2.15. Table 'xxx' doesn't exist エラー
A.2.16. Can't initialize character set xxx エラー
A.2.17. File Not Found エラー
A.3. インストール関連の問題
A.3.1. MySQL クライアントライブラリにリンク時の問題
A.3.2. 一般ユーザで MySQL を実行する方法
A.3.3. ファイルアクセス権の問題
A.4. 管理関連の問題
A.4.1. MySQL が何度もクラッシュする場合に行うこと
A.4.2. 忘れたルートパスワードをリセットする方法
A.4.3. フルディスク時の MySQL の動作
A.4.4. MySQL がテンポラリファイルを格納する場所
A.4.5. MySQL ソケットファイル /tmp/mysql.sock の保護または変更方法
A.4.6. タイムゾーンの問題
A.5. クエリ関連の問題
A.5.1. 検索時のケース依存
A.5.2. DATE カラム使用時の問題
A.5.3. NULL 値の問題
A.5.4. alias の問題
A.5.5. 関連テーブルからのレコードの削除
A.5.6. 不整合レコードの問題解決
A.5.7. 浮動小数点比較の問題
A.6. オプティマイザ関連の問題
A.6.1. テーブルスキャンを回避する方法
A.7. テーブル定義関連の問題
A.7.1. ALTER TABLE の問題
A.7.2. テーブルのカラム順序を変更する方法
A.7.3. テンポラリテーブルの問題

この章では、ユーザが遭遇するいくつかの一般的な問題とエラーメッセージについて説明しています。どんな問題か見分ける方法と、問題を解決するために行わなければならないことがわかります。また、一般的な問題の適切な解決方法についても記載されています。

A.1. 問題の原因を突き止める方法

問題に遭遇した場合、まず、問題の原因となっているプログラムまたは装置を突き止めます。

  • 以下の症状がある場合は、ハードウェア(メモリ、マザーボード、CPU、ハードディスク)の問題かカーネルの問題である可能性あり。

    • キーボードが動作しない。これは通常、CapsLock キーを押すことで確認できる。CapsLock ライトが変わらない場合は、キーボードを取り替える必要がある(これを行う前に、コンピュータを再起動し、キーボードに接続されているすべてのケーブルを確認する)。

    • マウスポインタが動かない。

    • マシンがリモートマシンの ping に応答しない。

    • 複数の無関係のプログラムが正しく動作しない。

    • システムが予期せず再起動した場合(誤ったユーザレベルのプログラムは、決してシステムを停止できない)。

    この場合、まずケーブルをすべて確認し、その後いくつかの診断ツールを実行してハードウェアを確認する。 また、問題が解決される可能性のある、使用しているオペレーティングシステム用の修正プログラム、アップデート、または Service Pack があるかどうかを確認する。 すべてのライブラリ(glibc など)が最新であることも確認する。

    メモリ問題を早期に検出するためには ECC メモリ内蔵のマシンが有効である。

  • キーボードがロックされている場合、別のユーザからマシンにログインし、kbd_mode -a を実行してロックを解除できる場合がある。

  • 問題の原因を突き止めるためには、システムログファイル(/var/log/messages など)を調べる。問題が MySQL にあると考えられる場合は、MySQL のログファイルも調べる必要がある。 See 項4.10.4. 「バイナリログ」

  • ハードウェアの問題ではないと考えられる場合には、問題の原因となるプログラムを突き止める必要がある。

    toppstaskmanager や同様のプログラムを使用して、すべての CPU を占有してしまっているプログラムや、マシンをロックしているプログラムを調べる。

  • topdf や同様のプログラムを使用して、メモリ、ディスク領域、開いているファイルや他の重要なリソースが不足しているかどうかを確認する。

  • 暴走プロセスが問題となっている場合は、まずその強制終了を試みる。強制終了されない場合は、オペレーティングシステムにバグがある可能性がある。

他の可能性をすべて調査し、問題の原因となっているのが MySQL サーバか MySQL クライアントであると結論づいた場合には、弊社メーリングリストまたはサポートチームにバグレポートをお送りください。バグレポートには、システムの動作、および発生していると考えられることを、詳細に記載してください。また、問題の原因が MySQL であると考えられる理由についても記入してください。この章のすべての状況を考慮に入れてください。システムを調査したときに、問題がどのように発生したかを正確に記入してください。プログラムまたはログファイルの出力またはエラーメッセージを記入する場合は、'カット & ペースト' を使用してください。

動作していないプログラムおよびすべての症状を詳細に記述するようにしてください。過去、"システムが動作しない" としか記述されていないバグレポートを多く受け取りました。これでは、何が問題なのかわかりません。

プログラムが失敗する場合は、以下を確認すると役立ちます。

  • そのプログラムがセグメンテーションフォルトしてコアダンプを作成しているか。

  • プログラムが CPU を占有しているか。top でチェックする。何か重い処理を行っている可能性があるため、プログラムをしばらく動作させる。

  • 問題の原因が mysqld サーバである場合は、mysqladmin -u root ping または mysqladmin -u root processlist を実行できるか。

  • MySQL サーバに接続しようとすると、クライアントプログラムにどのようなメッセージが表示されるか(たとえば、mysql で試す)。 クライアントが動かなくなるか。プログラムから何か出力があるか。

バグレポートをお送りいただく際には、このマニュアルに記載されている原則に従ってください。 See 項1.7.1.2. 「質問またはバグの報告」

A.2. MySQL 使用時によくあるエラー

このセクションでは、頻繁に発生するいくつかのエラーについて説明します。エラーの内容と問題の解決方法を説明します。

A.2.2. MySQL server has gone away エラー

このセクションでは、関連する Lost connection to server during query エラーもカバーしています。

MySQL server has gone away エラーの最も一般的な原因は、サーバがタイムアウトして接続がクローズしたことです。デフォルトでは、何も起きない状態が 8 時間続くと、サーバは接続をクローズします。この時間は、mysqld 開始時に wait_timeout 変数を設定することで変更できます。

MySQL server has gone away エラーが発生する一般的なもう一つの原因としては、MySQL とのコネクション上で ``close'' を発行し、クローズしたコネクションでクエリを実行しようとしたことが考えられます。

スクリプトがある場合は、クライアントが自動再接続を実行するためのクエリを再発行するだけで解決します。

この場合、通常以下のエラーコードが取得されます(OS 依存です)。

エラーコード説明
CR_SERVER_GONE_ERRORクライアントがサーバに問い合わせを送信できませんでした。
CR_SERVER_LOSTクライアントがサーバに書き込みを行った際エラーは発生しませんでしたが、問い合わせに対して完全な回答(または何らかの回答)が返ってきませんでした。

誰かが kill #スレッドID# で実行中のスレッドを強制終了した場合も、このエラーが発生します。

mysqladmin version を実行し、使用可能時間を調べることによって、MySQL が強制終了されていないことを確認できます。問題が mysqld のクラッシュであれば、クラッシュの理由を見つけ出すことに注力してください。 この場合、まずクエリを再発行して、MySQL が再び強制終了されるかどうかをチェックする必要があります。 See 項A.4.1. 「MySQL が何度もクラッシュする場合に行うこと」

間違ったクエリか大きすぎるクエリをサーバに送信した場合も、このエラーが発生する可能性があります。mysqld は大きすぎるか異常のあるパケットを取得すると、クライアントに何か問題が発生したとみなし、接続をクローズします。大きなクエリが必要な場合(たとえば、大きな BLOB カラムを使用している場合)、mysqld-O max_allowed_packet=# オプション(デフォルト 1MB)で起動して、クエリ制限を引き上げることができます。拡張メモリは要求に応じて割り当てられます。そのため、mysqld は、ユーザが大きなクエリを発行するときや、mysqld が大きな結果レコードを返す必要のあるときだけ、メモリを増やして割り当てます。

クライアントが 4.0.8 より古く、サーバが 4.0.8 以上の場合、またはその逆の場合、16MB 以上のパケットを送信すると接続が失われます。

この問題についてバグレポートを作成する際には、必ず以下の情報を記入してください。

See 項1.7.1.2. 「質問またはバグの報告」

A.2.3. Can't connect to [local] MySQL server エラー

Unix上の MySQL は mysqld サーバに次の2つの方法で接続することができます。Unix ソケット、これはファイルシステム上のファイル(デフォルトでは /tmp/mysqld.sock)を通して接続します。または TCP/IPで、これはポート番号を通して接続します。 Unix ソケットは、TCP/IP より高速ですが、同じコンピュータのサーバに接続する場合にしか使用できません。Unix ソケットは、ホスト名を指定しない場合、または特別なホスト名 localhost を指定する場合に使用されます。

Windows では、mysqld サーバが 9x/Me で動作している場合、TCP/IP を介してのみ接続できます。サーバが NT/2000/XP で動作しており、mysqld が --enable-named-pipe で起動している場合は、名前付きパイプと接続することもできます。名前付きパイプの名前は MySQL です。 mysqld に接続する際にホスト名を与えない場合は、MySQL クライアントは最初に名前付きパイプに接続しようとします。これが正しく機能しない場合は、TCP/IP ポートに接続します。ホスト名として . を使用することにより、Windows の名前付きパイプを強制的に使用できます。

エラー(2002)Can't connect to ... は、通常、MySQL サーバがシステム上で動作していないか、間違ったソケットファイルや TCP/IP ポートを使用して、mysqld サーバに接続しようとした場合に発生します。

サーバ上で mysqld というプロセスが動作しているかどうか、(ps か、Windows の場合はタスクマネージャを使用して)最初に確認してください。mysqld プロセスがなければ、これを起動してください。 See 項2.4.2. 「MySQL サーバの起動に関する問題」

mysqld プロセスが動作している場合は、さまざまな接続を試してサーバを確認できます(ポート番号とソケットのパス名は、当然セットアップ時と異なる可能性があります)。

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h 'ip for your host' version
shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version

hostnameコマンドは、フォワードクォートではなくバッククォートで囲んでください。これによって、hostname の出力(つまり現在のホスト名)が mysqladmin コマンドに代入されます。

Can't connect to local MySQL server エラーが発生する理由として、以下のことが考えられます。

  • mysqld が動作していない。

  • MIT-pthreads を使用するシステム上で実行している。 ネイティブスレッドを持たないシステムで実行している場合、mysqld は MIT-pthreads パッケージを使用する。See 項2.2.3. 「MySQL がサポートしているオペレーティングシステム」。ただし、すべてのMIT-pthreads バージョンが Unix ソケットをサポートしているわけではない。ソケットサポートのないシステムでは、サーバに接続する際に、常にホスト名を明示的に指定する必要がある。以下のコマンドを使用して、サーバへの接続を確認する。

    shell> mysqladmin -h `hostname` version
    

  • 誰かが、mysqld が使用する Unix ソケット(デフォルトでは /tmp/mysqld.sock)を削除した。MySQL ソケットを削除する cron ジョブ(たとえば、/tmp ディレクトリから古いファイルを削除するジョブ)を行っている可能性がある。mysqladmin version を実行し、mysqladmin が使用するソケットが本当に存在するかどうかを常にチェックすることができる。この場合の修正方法は、mysqld.sock を削除しないように cron ジョブを変更するか、ソケットを別の場所に移動させることである。 See 項A.4.5. 「MySQL ソケットファイル /tmp/mysql.sock の保護または変更方法」

  • --socket=/path/to/socket オプションを指定して、mysqld サーバを開始した。サーバのソケットパス名を変更する場合は、MySQL クライアントに新しいパスを通知する必要がある。パスを通知するには、ソケットパスを引数としてクライアントに提供する。 See 項A.4.5. 「MySQL ソケットファイル /tmp/mysql.sock の保護または変更方法」

  • Linux を使用中にスレッドが 1 つ消滅した(コアダンプした)。この場合、(たとえば、新しい MySQL サーバを実行する前に mysql_zap スクリプトを使用して)他の mysqld スレッドを強制終了する必要がある。 See 項A.4.1. 「MySQL が何度もクラッシュする場合に行うこと」

  • ソケットファイルを保持しているディレクトリ、またはソケットファイル自体への読み取り権限と書き込み権限がない可能性がある。この場合、アクセス可能なディレクトリを使用するように、ディレクトリまたはファイルに対する権限を変更するか、mysqld を再起動する必要がある。

エラーメッセージ Can't connect to MySQL server on some_hostname が発生した場合は、以下を行って問題を突き止めることができます。

  • telnet your-host-name tcp-ip-port-number を実行してサーバが立ち上がっているかどうかを確認し、Enter キーを数回押す。このポートで MySQL サーバが動作している場合は、動作中の MySQL サーバのバージョン番号を含むレスポンスが返ってくる。telnet: Unable to connect to remote host: Connection refused などのエラーが発生する場合は、サーバは所定のポートで動作していない。

  • ローカルマシンの mysqld デーモンに接続し、mysqladmin variablesmysqld が使用するように設定された TCP/IP ポート(変数 port)を確認する。

  • mysqld サーバが、--skip-networking オプションで起動されていないか確認する。

A.2.4. Client does not support authentication protocol エラー

MySQL 4.1 では、パスワードハッシュアルゴリズムに基づく認証プロトコルが使用されていますが、これは旧クライアントが使用しているものと互換性がありません。 サーバを 4.1 にアップグレードすると、旧クライアントで接続しようとした場合に、以下のエラーメッセージが発生する可能性があります。

shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

この問題を解決するには、以下のいずれかを行ってください。

  • 全クライアントプログラムをアップグレードして、4.1.1 以降のクライアントライブラリを使用するようにする。

  • 4.1 より前のクライアントから接続する場合は、旧パスワードでユーザアカウントを使用する。

  • 4.1 より前のクライアントを必要とするユーザをリセットし、旧パスワードを使用するようにする。

    mysql> UPDATE user SET Password = OLD_PASSWORD('mypass')
        -> WHERE Host = 'some_host' AND User = 'some_user';
    mysql> FLUSH PRIVILEGES;
    

  • サーバが旧パスワードハッシュアルゴリズムを使用するように指定する。

    1. --old-passwords を指定して mysqld を開始する。

    2. ロングパスワードを持っているユーザすべてのパスワードを設定する。これらのユーザは、以下で調べることができる。

      SELECT * FROM mysql.user WHERE LEN(password) > 16;
      

パスワードハッシュと認証の背景については、項4.3.11. 「MySQL 4.1 のパスワードハッシュ」 を参照してください。

A.2.5. Host '...' is blocked エラー

以下のエラーが発生した場合

Host 'hostname' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

これは、mysqld'hostname' ホストから多くの接続エラー(max_connect_errors)を受けた場合に発生します。max_connect_errors 大量発生後、mysqld は何か問題(クラッカーからの攻撃など)が発生したと判断し、このホストからの接続を拒否するようにします。これを解除するには、mysqladmin flush-hosts コマンドを実行します。

デフォルトでは、接続エラーが 10 回発生すると、mysqld はそのホストを拒否します。 この値は、以下のようにサーバを開始することで簡単に変更できます。

shell> mysqld_safe -O max_connect_errors=10000 &

特定のホストに対してこのエラーメッセージが発生する場合は、まず、そのホストからの TCP/IP 接続に問題がないか確認してください。TCP/IP 接続が機能していない場合は、max_connect_errors 変数の値を増やしても効果はありません。

A.2.6. Too many connections エラー

MySQL に接続しようとして Too many connections エラーが発生する場合は、すでに mysqld サーバに接続している max_connections クライアントが存在しています。

デフォルト(100)より多い接続を行う場合は、max_connections 変数の値を 100 より大きくして、mysqld を再起動する必要があります。

実際は、mysqld では(max_connections+1)クライアントの接続が許可されています。最後の接続は、SUPER 特権のあるユーザ用に予約されています。一般ユーザにこの特権を与えないことによって(一般ユーザにこの特権は必要ありません)、この特権のある管理者はログインして、SHOW PROCESSLIST を使用して問題を見つけることができます。 See 項4.6.8.6. 「SHOW PROCESSLIST

MySQL 接続の最大数は、スレッドライブラリが特定のプラットフォームでどの程度まで有用であるかに依存します。Linux または Solaris では、使用している RAM のサイズと、クライアントが何を実行しているかによって、500 ? 1000 の同時接続をサポートできます。

A.2.7. Some non-transactional changed tables couldn't be rolled back エラー

ROLLBACK を実行しようとしたときに Warning: Some non-transactional changed tables couldn't be rolled back が発生した場合、トランザクションで使用したテーブルの中にトランザクションをサポートしていないものがあることを示しています。これら非トランザクションテーブルは、ROLLBACK ステートメントからの影響を受けません。

最も一般的には、このエラーが発生するのは、mysqld バイナリでサポートされていない型のテーブルを作成しようとしたときです。 mysqld がテーブル型をサポートしていない場合(またはスタートアップオプションでテーブル型が無効化されている場合)、代わりに、要求したものと最も類似したテーブル型(おそらく MyISAM)が作成されます。

以下のコマンドでテーブルのテーブル型を確認できます。

SHOW TABLE STATUS LIKE 'table_name'。 See 項4.6.8.2. 「SHOW TABLE STATUS

以下のコマンドで mysqld バイナリがサポートする拡張子を確認できます。

SHOW VARIABLES LIKE 'have_%'。 See 項4.6.8.4. 「SHOW VARIABLES

A.2.8. Out of memory エラー

クエリを発行し、以下のようなエラーが発生した場合

mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory

エラーが MySQL クライアント mysql を参照していることに注意してください。このエラーの原因は、クライアントにすべての結果を格納するだけのメモリがないことです。

問題を解決するには、まず、クエリが正しいことを確認してください。そのクエリは大量のレコードを返すものでしょうか ? そうであれば、mysql --quick を使用できます。これは、結果セットを取り出すために mysql_use_result() を使用します。これによってクライアントの負荷が小さくなります(サーバ側では負荷が大きくなります)。

A.2.9. Packet too large エラー

MySQL クライアントまたは mysqld サーバが max_allowed_packet バイトより大きいパケットを受け取った場合、Packet too large エラーが発生し、接続がクローズされます。

MySQL 3.23 で使用できる最も大きなパケットは 16M です(クライアントおよびサーバプロトコルの制限によります)。MySQL 4.01 以上では、パケットの大きさは、サーバ上のメモリ容量でのみ制限されます(理論上は最大 2G)。

1 つの通信パケットは、MySQL サーバに送信される単一の SQL ステートメントか、クライアントに送信される単一行です。

MySQL クライアントまたは mysqld サーバが max_allowed_packet バイトより大きいパケットを受け取った場合は、Packet too largeエラーが発生し、接続がクローズされます。クライアントの中には、通信パケットが大きすぎると Lost connection to MySQL server during query エラーを発生するものもあります。

クライアントとサーバには、共に独自の max_allowed_packet 変数があります。大きなパケットを扱う場合は、クライアントとサーバ両方の変数を増やす必要があります。

メモリは必要な場合にのみ割り当てられるため、この変数を増やしても安全です。この変数は、クライアントとサーバ間の不正なパケットを捕捉したり、メモリ不足になってしまうような大きなパケットを誤って使用したりしないための予防策です。

mysql クライアントを使用している場合は、クライアントを mysql --set-variable=max_allowed_packet=8M で開始することで、より大きなバッファを指定することができます。 他のクライアントには、この変数を設定する別の方法があります。 MySQL 4.0 以降、--set-variable は使用されなくなっています。代わりに --max-allowed-packet=8M を使用してください。

オプション設定ファイルを使用すると、mysqldmax_allowed_packet をより大きなサイズに設定することができます。たとえば、MEDIUMBLOB の許容範囲いっぱいのデータをテーブルに入れる場合、--set-variable=max_allowed_packet=16M オプションを指定してサーバを起動します。

大きな BLOB を使用している場合、大きなパケットに関する見慣れない問題が発生する可能性がありますが、これは、mysqld に、そのクエリを処理できるだけの十分なメモリへのアクセス権がないことが原因です。その場合は、mysqld_safe スクリプトの始めに ulimit -d 256000 を追加して、mysqld を再起動してください。

A.2.10. 通信エラー/Aborted connection

MySQL 3.23.40 から、mysqld--warnings で開始した場合のみ、Aborted connection エラーが発生します。

エラーログに以下のようなエラーが含まれている場合は、

010301 14:38:23  Aborted connection 854 to db: 'users' user: 'josh'

See 項4.10.1. 「エラーログ」

以下が発生したと考えられます。

  • クライアントプログラムが終了前に mysql_close() を呼び出さなかった。

  • クライアントが何の要求もせずに、wait_timeout または interactive_timeout より多くの時間スリープ状態であった。 See 項4.6.8.4. 「SHOW VARIABLES

  • クライアントプログラムが、転送中に突然終了した。

上記のことが発生した場合、サーバ変数 Aborted_clients の値が増えます。

以下の場合、サーバ変数 Aborted_connects の値が増えます。

  • 接続パケットに正しい情報が含まれていない場合

  • ユーザにデータベースに接続する権限がない場合

  • ユーザが間違ったパスワードを使用した場合

  • 接続パケットの取得に、connect_timeout で指定されている秒数より多く要した場合 See 項4.6.8.4. 「SHOW VARIABLES

上記のことは、不正ユーザがデータベースに侵入しようとしている可能性を示しています。

中止されたクライアントおよび中止された接続エラーのその他の原因

  • Linux での Ethernet プロトコルの使用(半二重と全二重)。 多くの Linux Ethernet ドライバには、このバグがある。2つのマシン間で ftp を使用して大きなファイルを転送し、このバグについてテストする必要がある。 転送が burst-pause-burst-pause ... モードで行われている場合は、Linux 二重シンドロームに陥っている。 唯一の解決策は、ネットワークカードとハブ/スイッチの二重モードを、全二重または半二重に切り替え、その結果をテストし最も良い設定を行うことである。

  • 読み取りの中断の原因になるスレッドライブラリの問題。

  • TCP/IP の設定間違い。

  • 不良 Ethernet、ハブ、スイッチ、ケーブルなど。これは、ハードウェアを交換してみることでしか正しく診断できない。

  • max_allowed_packet が小さすぎるか、クエリが mysqld に割り当てられたメモリより多くのメモリを必要としている。 See 項A.2.9. 「Packet too large エラー」

A.2.11. The table is full エラー

このエラーが発生するケースとしては、以下のようなさまざまなケースが考えられます。

  • 旧バージョン(3.23.0 より前)の MySQL を使用していて、メモリ内のテンポラリテーブルが tmp_table_size バイトより大きくなったとき。 この問題を回避するには、-O tmp_table_size=# オプションを使用して mysqld でテンポラリテーブルサイズを大きくするか、問題のクエリを発行する前に、SQL オプション SQL_BIG_TABLES を使用する。 See 項5.5.6. 「SET 構文」

    また、--big-tables オプションを指定して mysqld を開始することもできる。 これは、すべてのクエリに SQL_BIG_TABLES を使用しているのとまったく同じ。

    MySQL バージョン 3.23 では、メモリ内のテンポラリテーブルが tmp_table_size より大きくなると、サーバがそのテーブルを自動的にディスクベースの MyISAM テーブルに変換した。

  • InnoDB テーブルを使用しており、InnoDB のテーブルスペースが不足している。この問題を解決するには、InnoDB のテーブルスペースを拡張する。

  • サイズが 2GB のファイルしかサポートしていない OS で ISAM または MyISAM テーブルを使用しており、データファイルまたはインデックスファイルが制限に達した。

  • MyISAM テーブルを使用しており、必要なデータまたはインデックスサイズが、MySQL がポインタを割り当てたものより大きくなっている(MAX_ROWSCREATE TABLE に指定しない場合は、MySQL は 4G のデータを保持できる分だけポインタを割り当てる)。

    最大データとインデックスサイズを確認できる。確認するには、以下のコマンドを実行するか、

    SHOW TABLE STATUS FROM database LIKE 'table_name';
    

    myisamchk -dv database/table_name を使用する。

    これで問題がある場合は、以下の方法で解決できる。

    ALTER TABLE table_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;
    

    この場合、MySQL はレコード数だけに基づいて必要なスペースを最適化することができないので、BLOB/TEXT フィールドをもつテーブルに AVG_ROW_LENGTH を指定することが必要になる。

A.2.12. Can't create/write to file エラー

以下のようなクエリのエラーが発生する場合

Can't create/write to file '\\sqla3fe_0.ism'.

MySQL が、特定のテンポラリディレクトリに結果セット用のテンポラリファイルを作成できないことを示しています(上記のエラーは、Windows での典型的なエラーメッセージですが、Unix でのエラーメッセージもよく似たメッセージになります)。 解決するには、--tmpdir=path を指定して mysqld を起動するか、オプション設定ファイルに以下のコードを追加します。

[mysqld]
tmpdir=C:/temp

c:\\temp ディレクトリが存在していると仮定しています。 See 項4.1.2. 「my.cnf オプション設定ファイル」

また perror で、取得するエラーコードを確認します。1つの原因としてディスクがいっぱいになっていることも考えられます。

shell> perror 28
Error code  28:  No space left on device

A.2.13. クライアントでの Commands out of sync エラー

クライアントコードの中に Commands out of sync; you can't run this command now がある場合は、間違った順序でクライアント関数を呼び出しています。

たとえば、mysql_free_result() を呼び出す前に mysql_use_result() を使って新しいクエリを実行しようとすると、上記のことが起こる可能性があります。 また、データを返す 2つのクエリを、その間に mysql_use_result()mysql_store_result() を呼び出さないで実行した場合にも起こる可能性があります。

A.2.14. Ignoring user エラー

次のエラーが発生する場合

Found wrong password for user: 'some_user@some_host'; ignoring user

mysqld が再起動されたとき、またはアクセス権テーブルが再ロードされたときに、user テーブルに無効なパスワードのエントリが見つかったことを示しています。結果として、このエントリはアクセス権システムから無視されます。

この問題の考えられる原因と修正方法

  • user テーブルで新バージョンの mysqld を実行している可能性がある。 mysqlshow mysql user を実行し、パスワードフィールドが 16 文字より短いかどうかを調べることによって、このことを確認できる。短い場合、scripts/add_long_password スクリプトを実行して、この状態を修正できる。

  • ユーザのパスワードは旧パスワード(8 文字長)であるが、mysqld--old-protocol オプションで開始されなかった。 user テーブルのユーザを新規パスワードで更新するか、mysqld--old-protocol を指定して再起動する。

  • PASSWORD() 関数を使用せずに、user テーブルにパスワードを指定した。mysql を使用して user テーブルのユーザを新規パスワードで更新する。このとき、必ず PASSWORD() 関数を使用すること。

    mysql> UPDATE user SET password=PASSWORD('your password')
        ->             WHERE user='XXX';
    

A.2.15. Table 'xxx' doesn't exist エラー

エラー Table 'xxx' doesn't exist または Can't find file: 'xxx' (errno: 2) が発生する場合、xxx という名前のカレントデータベースにテーブルがないことを示しています。

MySQL では、データベースとテーブルの格納にディレクトリとファイルを使用するため、データベースとテーブル名は、大文字と小文字の区別がある(ケース依存)ことに注意してください (Windows では、データベースとテーブル名に大文字小文字の区別がありません。しかし、クエリ内の特定テーブルへの参照では大文字と小文字を完全に合わせる必要があります)。

SHOW TABLES を使用して、カレントデータベースにあるテーブルを確認できます。 See 項4.6.8. 「SHOW 構文」

A.2.16. Can't initialize character set xxx エラー

以下のエラーが発生した場合

MySQL Connection Failed: Can't initialize character set xxx

以下のことが考えられます。

  • キャラクタセットがマルチバイトのキャラクタセットであるが、クライアントではキャラクタセットがサポートされていない。

    この場合、クライアントを --with-charset=xxx または --with-extra-charsets=xxx で再コンパイルする。 See 項2.3.3. 「一般的な configure オプション」

    標準 MySQL バイナリはすべて --with-extra-character-sets=complex でコンパイルされている。これによって、マルチバイトのキャラクタセットすべてがサポートされる。 See 項4.7.1. 「データおよびソート用キャラクタセット」

  • キャラクタセットが単純なキャラクタセットで、それが mysqld に組み込まれておらず、キャラクタセットの定義ファイルがクライアントの予想する場所にない。

    この場合、以下のようにする。

    • キャラクタセットをサポートするように、クライアントを再コンパイルする。 See 項2.3.3. 「一般的な configure オプション」

    • クライアントに、キャラクタセットの定義ファイルの場所を通知する。多くのクライアントに対して、--character-sets-dir=path-to-charset-dir オプションを使用して通知するできる。

    • 文字定義ファイルを、クライアントがその定義ファイルがあると予想しているパスにコピーする。

A.2.17. File Not Found エラー

MySQL から ERROR '...' not found (errno: 23)Can't open file: ... (errno: 24)、または errno 23 または errno 24 とともに他のエラーを受け取った場合、MySQL に十分なファイル記述子が割り当てられていないことを示しています。perror ユーティリティを使用して、エラー番号が何を意味しているか、その内容を取得することができます。

shell> perror 23
File table overflow
shell> perror 24
Too many open files
shell> perror 11
Resource temporarily unavailable

ここでの問題は、mysqld が非常に多くのファイルを同時に開こうとしていることです。mysqld が同時に多くのファイルを開かないように指定するか、mysqld で使用できるファイル記述子の数を増やすことができます。

mysqld で同時に開くファイルを少なくするために、mysqld_safe-O table_cache=32 オプション(初期値は 64)を指定して、テーブルキャッシュを小さくすることができます。max_connections の値を減らすことで、オープンファイル数(初期値は 90)も少なくなります。

mysqld で使用できるファイル記述子の数を変更するために、mysqld_safe--open-files-limit=# オプション、または mysqld-O open-files-limit=# オプションを使用することができます。 See 項4.6.8.4. 「SHOW VARIABLES。 これを行う最も簡単な方法は、オプション設定ファイルにオプションを追加することです。 See 項4.1.2. 「my.cnf オプション設定ファイル」。 これをサポートしていない旧バージョンの mysqld を使用している場合は、mysqld_safe スクリプトを編集することができます。スクリプトにはコメントアウトされた ulimit -n 256 行があります。'#' 文字を削除してこの行のコメントを解除し、数字 256 を変更することができます。これによって、 mysqld で使用できるファイル記述数も変わります。

ulimit(および open-files-limit)によって、ファイル記述子の数を増やすことができます。しかし、オペレーティングシステムで定められた上限までしか増やせません。また 'ハード' リミットが存在し、ルートとして mysqld_safe または mysqld を開始した場合に限り上書きすることができます(この場合、--user=... オプションも使用する必要があります)。各プロセスで利用できるファイル記述子の数の OS 制限を増やす必要がある場合は、そのオペレーティングシステムのドキュメントを参照してください。

tcsh シェルを実行している場合は、ulimit は機能しません。 tcsh は、現在の制限について問い合わせると、間違った値を返します。この場合、mysqld_safesh で開始する必要があります。

A.3. インストール関連の問題

A.3.1. MySQL クライアントライブラリにリンク時の問題

プログラムをリンクするときに、mysql_ で始まる未参照シンボルに関する以下のようなエラーが発生する場合

/tmp/ccFKsdPa.o: In function `main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

これは、リンク行の最後-Lpath-to-the-mysql-library-lmysqlclient を追加すると解決できます。

uncompress または compress 関数で undefined reference エラーが発生する場合は、リンク行の最後-lz を追加して再度実行してください。

システムにあるはずの関数(例: connect)に対して undefined reference エラーが発生する場合は、該当する関数を man ページで確認し、そのライブラリをリンク行に追加するかどうか判断してください。

以下のように、システムに存在しない関数で undefined reference エラーが発生する場合

mf_format.o(.text+0x201): undefined reference to `__lxstat'

これは、通常、使用しているシステムと 100% 互換でないシステム上でライブラリがコンパイルされていることを示しています。この場合、最新の MySQL ソースディストリビューションをダウンロードし、それを独自にコンパイルしてください。 See 項2.3. 「MySQL ソースディストリビューションのインストール」

プログラムを実行しようとしているが、mysql_ で始まるエラーか、mysqlclient ライブラリが見つからない未参照シンボルのエラーが発生する場合は、システムが libmysqlclient.so 共有ライブラリを見つけられないということを示しています。

これを解決するには、以下のいずれかの方法で、関数が組み込まれている共用ライブラリを検索するように、システムに指示します。

  • LD_LIBRARY_PATH 環境変数に libmysqlclient.so が存在するディレクトリのパスを追加する。

  • LD_LIBRARY 環境変数に libmysqlclient.so が存在するディレクトリのパスを追加する。

  • libmysqlclient.so をシステムが検索する場所(たとえば /lib)にコピーし、ldconfig を実行して共有ライブラリ情報を更新する。

この問題を解決するもう 1つの方法として、-static を使用するか、コードをリンクする前に MySQL の動的ライブラリを削除して、プログラムを静的にリンクする方法があります。2 番目のケースでは、別のプログラムが動的ライブラリを使用していないことを確認する必要があります。

A.3.2. 一般ユーザで MySQL を実行する方法

MySQL サーバ mysqld は、どんな Unix ユーザでも開始、実行できます。 mysqld を Unix ユーザ user_name で実行できるように変更するには、以下を行ってください。

  1. サーバが動作している場合は、それを停止します(mysqladmin shutdown を使用します)。

  2. データベースのディレクトリとファイルを変更して、その中のファイルを読み込んだり書き込んだりする権限を user_name に与えます(場合によっては Unix root ユーザとして行う必要があります)。

    shell> chown -R user_name /path/to/mysql/datadir
    

    MySQL データディレクトリ内のディレクトリまたはファイルがシンボリックリンクの場合は、リンクに従い、そのファイルやディレクトリが指しているディレクトリとファイルも変更する必要があります。chown -R では、シンボリックリンク先まで変更できません。

  3. サーバを user_name で開始するか、MySQL バージョン 3.22 以降を使用している場合は、mysqld をUnix root ユーザで開始して、--user=user_name オプションを使用します。mysqld は、接続を許可する前に、Unix ユーザ user_name での実行に切り替わります。

  4. システム起動時にサーバを特定のユーザ名で自動的に開始するには、ユーザ名を指定する user 行を、/etc/my.cnf オプション設定ファイルかサーバのデータディレクトリにある my.cnf オプション設定ファイルの [mysqld] グループに追加します。たとえば、以下のようにします。

    [mysqld]
    user=user_name
    

この時点で、mysqld プロセスは Unix ユーザ user_name として正常に動作します。ただし、アクセス権テーブルの内容は変わりません。デフォルトでは(アクセス権テーブルのインストールスクリプト mysql_install_db の実行直後)、mysql データベースへのアクセスまたはデータベースの作成や破棄の権限を持つ唯一のユーザは MySQL ユーザ root です。これらのアクセス権を変更しなかった場合、そのアクセス権はそのまま保持されます。root 以外の Unix ユーザとしてログインしている場合も、MySQL root ユーザとしてMySQLにアクセスできます。そのために行うことは、-u root オプションをクライアントプログラムに指定するだけです。

コマンドラインで -u root を指定して、root としてMySQL にアクセスすることと、Unix root ユーザ、または実際には別の Unix ユーザとして MySQL を実行することとは何の関係もありません。MySQL のアクセス権とユーザ名は、Unix ユーザ名とは完全に別のものです。Unix ユーザ名と唯一関連があるのは、クライアントプログラムを呼び出すときに -u オプションを指定しない場合に、クライアントが MySQL ユーザ名として Unix ログイン名を使用して接続を試みるということだけです。

Unix ボックスそのものが保護されていない場合は、少なくとも、アクセステーブルの MySQL root ユーザにパスワードを設定しておく必要があります。 そうしなければ、マシンにアカウントのあるユーザは、mysql -u root db_name を実行して思い通りのことを行えます。

A.3.3. ファイルアクセス権の問題

ファイルアクセス権に問題がある場合、たとえばテーブルを作成する際に mysql が以下のエラーメッセージを発行した場合

ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)

mysqld 起動時に、環境変数 UMASK が正しく設定されていなかった可能性があります。umask 初期値は 0660 です。以下のように mysqld_safe を実行して、この動作を変更することができます。

shell> UMASK=384  # = 600 in octal
shell> export UMASK
shell> /path/to/mysqld_safe &

デフォルトでは、MySQL はアクセス権タイプ 0700 のデータベースと RAID ディレクトリを作成します。UMASK_DIR 変数を設定して、この動作を変更することができます。この変数を設定すると、UMASKUMASK_DIR が組み合わされて新しいディレクトリが作成されます。たとえば新しいディレクトリすべてにグループアクセス権を与える場合は、以下を実行します。

shell> UMASK_DIR=504  # = 8進数で 770
shell> export UMASK_DIR
shell> /path/to/mysqld_safe &

MySQL バージョン 3.23.25 以降では、UMASKUMASK_DIR の値がゼロで始まる場合、MySQL はその値を8進数と仮定します。

See 付録?F. 環境変数

A.4. 管理関連の問題

A.4.1. MySQL が何度もクラッシュする場合に行うこと

MySQL バージョンはすべて、リリース前に多くのプラットフォームでテストされています。これは MySQL にバグがないというわけではありませんが、バグがあったとしても、非常に少なく見つけるのが困難です。何か問題がある場合に、システムをクラッシュさせているものを正確に調査することは、この問題の早期解決に役立ちます。

まず、問題は mysqld デーモンが死んでいることにあるのか、または問題がクライアントに関係しているのかを判断する必要があります。mysqladmin version を実行して、mysqld サーバが稼動していた時間を確認することができます。mysqld が死んでいる場合は、ファイル mysql-data-directory/`hostname`.err を見ることによりその原因を見つけることができます。 See 項4.10.1. 「エラーログ」

システムの中には、このファイルに mysqld が死んだ際のスタックトレースがあるものがあり、resolve_back_stack で問題を解決できます。See 項E.1.4. 「スタックトレースの使用」.err ファイルに書き込まれている変数値は、常に 100 パーセント正確であるとは限りません。

MySQL のクラッシュの多くは、インデックスファイルやデータファイルの破壊が原因です。 MySQL は、すべての SQL ステートメントの後で write() システムコールを呼び出し、ディスク上のデータを更新します。クライアントには、その後その結果が通知されます(delay_key_write で実行している場合で、データの書き込みだけの場合にはこの限りではありません)。 つまり、OS によってフラッシュされていないデータがディスクに確実に書き込まれるため、mysqld がクラッシュした場合でもデータは安全です。--flush を指定して mysqld を開始することによって、各 SQL コマンド実行後、強制的にすべてをディスクと同期させることができます。

つまり、以下のことがなければ、通常は破壊されたテーブルを得ることはありません。

  • 誰かまたは何かが、更新中に mysqld またはマシンを強制終了した。

  • 更新中に mysqld が死ぬようなバグを見つけた。

  • テーブルを適切にロックしないで、mysqld 外でデータまたはインデックスフファイルを操作している。

  • 優れたファイルシステムロック(通常、lockd デーモンによって処理される)をサポートしていないシステム上で、同じデータに対して、多くの mysqld サーバを実行しているか、--skip-external-locking で複数サーバを実行している。

  • mysqld を混乱させるような不正なデータを含んだ、破損したインデックスまたはデータファイルがある。

  • データストレージのコードにバグを発見した。これはおそらくあり得ないことだが、可能性としてはある。この場合、修正されたテーブルのコピーに対して ALTER TABLE を使用して、ファイルタイプを別のデータストレージエンジンに変更することができる。

クラッシュの原因を見つけるのは非常に難しいので、まず、他で動作しているものが自分の環境でクラッシュするかどうかを確認してください。以下を試してください。

mysqladmin shutdownmysqld デーモンを停止し、全テーブルで myisamchk --silent --force */*.MYI を実行した後、mysqld デーモンを再起動する。必ず、クリーンな状態から実行すること。 See 章?4. データベース管理

  • mysqld --log を使用して、ログの情報から、特定のクエリがサーバを終了させるかどうかを判断する。バグの 95% が特定のクエリに関係している。通常、これは、MySQL 再実行直前のログファイルにある最後のクエリの 1 つである。 See 項4.10.2. 「一般クエリログ」。 クエリを実行する直前にすべてのテーブルを確認しても、クエリの 1 つで MySQL を何度も強制終了させることができる場合、バグを突き止められているので、バグレポートを発行する必要がある。 See 項1.7.1.3. 「バグまたは問題を報告する方法」

  • 問題の再現に使用するテストケースを作成する。 See 項E.1.6. 「テーブルが破損した場合にテストケースを作成する」

  • 組み込まれている mysql-test テストと MySQL ベンチマークを実行する。See 項13.1.2. 「MySQL テストスイート」。これによって MySQL を正確にテストできる。ベンチマークにアプリケーションをシミュレートするコードを追加することもできる。ベンチマークは、ソースディストリビューションまたはバイナリディストリビューションの bench ディレクトリか、MySQL インストールディレクトリの sql-bench ディレクトリにある。

  • fork_test.plfork2_test.pl を実行する。

  • デバッグ用に MySQL を設定している場合は、何か問題が発生した際に、考えられるエラー情報の収集が非常に容易になる。 configure--with-debug オプションか --with-debug=full オプションを指定して MySQL を再設定し、その後再コンパイルする。 See 項E.1. 「MySQL サーバのデバッグ」

  • デバッグ用に MySQL を設定すると、安全なメモリアロケータが組み込まれ、エラーを見つけることができる。また、何が発生しているかについて、多くの情報が提供される。

  • オペレーティングシステムの最新のパッチを適用しているかどうか確認する。

  • mysqld にオプション --skip-external-locking を指定する。システムの中には、lockd ロックマネージャが適切に動作しないものがある。--skip-external-locking オプションによって、mysqld に外部ロックを使用しないように指示することができる(つまり、同じデータで 2 つの mysqld サーバを実行することができない。myisamchk を使用する場合は注意が必要だが、テストとしてオプションを使用する場合は有益である)。

  • mysqld が動作しているように見えるのに応答がなかった時、mysqladmin -u root processlist を実行したか。mysqld は消滅しているように見えても、消滅していない場合がある。すべての接続が使用中であるか、内部ロック問題の可能性がある。 mysqladmin processlist は、通常、このような場合であっても接続を行うことができ、現在の接続数やその状況に関して有益な情報を取得できる。

  • 他のクエリを実行中に、別のウィンドウで mysqladmin -i 5 status または mysqladmin -i 5 -r status を実行し、統計を生成する。

  • 以下を実行してみる。

    1. gdb から(または別のデバッガで)、mysqld を起動する。 See 項E.1.3. 「mysqld のデバッグ(gdb 使用)」

    2. テストスクリプトを実行する。

    3. 3つの最下位レベルで、バックトレースとローカル変数を出力する。gdb では、mysqld が gdb 内部でクラッシュした場合、以下のコマンドでこの出力を実行できる。

      backtrace
      info local
      up
      info local
      up
      info local
      

      gdb では、info threads により、存在しているスレッドを調べ、thread ## はスレッド ID)で特定のスレッドにスイッチすることができる。

  • Perl スクリプトでアプリケーションをシミュレートし、MySQL をクラッシュさせたり不正な動作をさせたりする。

  • バグレポートを送付する。See 項1.7.1.3. 「バグまたは問題を報告する方法」。詳細なレポートにすること。MySQL は多くの人が使用しているため、クラッシュがあなたのコンピュータだけにある何らかの原因に起因している可能性がある(たとえば、特定のシステムライブラリに関連するエラー)。

  • 可変長レコードを持つテーブルに問題があり、BLOB/TEXT カラム(BLOB/TEXT カラムのみ)を使用していない場合、ALTER TABLEVARCHAR すべてを CHAR に変更することができる。これによって、MySQL は固定サイズのレコードを使用する。 固定サイズのレコードは余分な領域を少し取るだけだが、破壊に対して非常に大きな耐性がある。

    現在の可変長レコードのコードは、少なくとも 3 年間は何の問題もなく MySQL AB で使用されてきた。しかし本来、可変長レコードはエラーが発生しやすく、上記のことが役立つかどうか試してみるのも有益である。

A.4.2. 忘れたルートパスワードをリセットする方法

MySQL に root パスワードを設定しないと、root として接続した場合に、サーバがパスワードを一切要求しなくなります。ユーザごとに常にパスワードを設定することをお勧めします。 See 項4.3.2. 「MySQL のクラッカー対策」

root パスワードを設定した後で、それを忘れてしまった場合、以下の手順で新しいパスワードを設定することができます。

  1. mysqld サーバに killkill -9 以外)を送り、mysqld サーバを停止します。pid が .pid ファイルに格納されています。このファイルは通常、MySQL データベースディレクトリにあります。

    shell> kill `cat /mysql-data-directory/hostname.pid`
    

    これを行うには、Unix root ユーザまたは mysqld が実行しているユーザと同じでなければなりません。

  2. --skip-grant-tables オプションを指定して mysqld を再起動します。

  3. mysqladmin password コマンドで新しいパスワードを設定します。

    shell> mysqladmin -u root password 'mynewpassword'
    

  4. これで、適切に mysqld を停止し再起動するか、以下のように、アクセス権テーブルをロードできるようになります。

    shell> mysqladmin -h hostname flush-privileges
    

  5. この後、新しいパスワードを使用して接続できます。

もう一つの方法として、mysql クライアントを使用して新しいパスワードを設定することができます。

  1. 上述したように、mysqld を停止して、--skip-grant-tables オプションを指定して再起動します。

  2. 以下のように、mysqld サーバに接続します。

    shell> mysql -u root mysql
    

  3. mysql クライアントで以下のコマンドを実行します。

    mysql> UPDATE user SET Password=PASSWORD('mynewpassword')
        ->             WHERE User='root';
    mysql> FLUSH PRIVILEGES;
    

  4. この後、新しいパスワードを使用して接続できます。

  5. これで、適切に mysqld を停止し、再起動できます。

A.4.3. フルディスク時の MySQL の動作

ディスクフル状態が発生した場合、MySQL では以下のことを行います。

  • 1 分ごとに 1 回、現在のレコードを書き込むために十分な空き領域があるかどうか確認する。十分な空き領域がある場合は、何も問題が発生しなかったように処理を続行する。

  • 6 分ごとにログファイルにエントリを書き込み、ディスクフル状態を警告する。

問題を軽減するために、以下を行うことができます。

  • 処理を続行するには、全レコードを挿入できるディスク領域を確保する必要がある。

  • スレッドを停止するには、mysqladmin kill をスレッドに送信する必要がある。 スレッドは、次にディスクがチェックされたとき(1分)に停止する。

  • 他のスレッドが、ディスクフル状態の原因となったテーブルを待機している可能性がある。複数の ``ロック'' スレッドがある場合、ディスクフル状態で待機しているスレッドを 1 つ強制終了すると、他のスレッドの処理を続行できる。

上記の動作の例外は、REPAIR または OPTIMIZE を使用しているときか、インデックスが LOAD DATA INFILE または ALTER TABLE ステートメントの後にバッチで作成されるときです。

上記のコマンドはすべて、大きなテンポラリファイルを使用する場合があるので、資源が残り少なくなったシステムに問題を引き起こす可能性があります。上記の操作を実行中に MySQL がディスクフル状態になると、大きなテンポラリファイルが削除され、テーブルはクラッシュしたものとしてマークされます(旧テーブルが変更されずに残る ALTER TABLE は除きます)。

A.4.4. MySQL がテンポラリファイルを格納する場所

MySQL は、テンポラリファイルを格納するディレクトリのパス名として、TMPDIR 環境変数の値を使用します。TMPDIR を設定していない場合、MySQL はシステムのデフォルトを使用します。システムのデフォルトは、通常 /tmp または /usr/tmp です。テンポラリファイルディレクトリを含むファイルシステムが非常に小さい場合、mysqld_safe を編集して、領域が十分あるファイルシステムのディレクトリを指すように TMPDIR を設定する必要があります。mysqld に対して --tmpdir オプションを使用しても、テンポラリディレクトリを設定できます。

MySQL はすべてのテンポラリファイルを隠しファイルとして作成します。これによって、mysqld が強制終了されるとテンポラリファイルは確実に削除されます。隠しファイル使用の不利な点は、テンポラリファイルディレクトリのあるファイルシステムをいっぱいにするような大きなテンポラリファイルが見えないことです。

ソート時(ORDER BY または GROUP BY により)、MySQL は通常、1つまたは2つのテンポラリファイルを使用します。必要な最大ディスク領域は、以下のとおりです。

(ソートされたものの長さ + sizeof(データベースポインタ))
* マッチするレコードの数
* 2

sizeof(データベースポインタ) は、通常 4 ですが、大きいテーブルに対応するため、将来的に増える可能性があります。

SELECT クエリの中には、MySQL が テンポラリ SQL テーブルを作成するものがあります。これらは隠しファイルではなく、SQL_* という名前になります。

ALTER TABLE では、元のテーブルと同じディレクトリにテンポラリテーブルが作成されます。

MySQL 4.1 以降を使用している場合、コロン :(Windows の場合はセミコロン ;)で区切られたパスのリストを --tmpdir に設定することにより、複数の物理ディスク間で負荷を分散させることができます。この物理ディスクは、ラウンドロビン方式で使用されます。 注意: これらのパスは、同一ディスクの複数のパーティションではなく、異なる物理ディスクである必要があります。

tmpdir を設定してメモリベースのファイルシステムを指定することは可能ですが、MySQL サーバがスレーブの場合はできません。スレーブの場合、コンピュータの再起動用に、いくつかのテンポラリファイルが必要(テンポラリテーブルまたは LOAD DATA INFILE のレプリケーションため)です。そのため、コンピュータの再起動で消去されるメモリベースの tmpdir は適しません。ディスクベースの tmpdir が必要です。

A.4.5. MySQL ソケットファイル /tmp/mysql.sock の保護または変更方法

すべての人が MySQL 通信ソケット /tmp/mysql.sock を削除できるということが問題であれば、Unix の多くのバージョンにおいて、/tmp ファイルシステムに sticky ビットを設定することにより、そのファイルシステムを保護できるようになっています。root としてログインし、以下を行います。

shell> chmod +t /tmp

これによって、/tmp ファイルシステムが保護され、ファイルの所有者かスーパーユーザ(root)しかファイルを削除できなくなります。

ls -ld /tmp を実行して、sticky ビットが設定されているかどうかを確認できます。 最後のアクセス権ビットが t であれば、ビットは設定されています。

MySQL がソケットファイルを使用または置く場所を、以下の方法で変更できます。

  • グローバルオプション設定ファイルまたはローカルオプション設定ファイルのパスを指定する。 たとえば、/etc/my.cnf に置く場合

    [client]
    socket=path-for-socket-file
    
    [mysqld]
    socket=path-for-socket-file
    

    See 項4.1.2. 「my.cnf オプション設定ファイル」

  • コマンドラインで --socket=path-for-socket-file オプションを使用して、mysqld_safe と大部分のクライアントに対してソケットを置く場所を指定する。

  • ソケットファイルのパスを、MYSQL_UNIX_PORT 環境変数で指定する。

  • configure--with-unix-socket-path=path-for-socket-file オプションとともに使用して、パスを定義する。 See 項2.3.3. 「一般的な configure オプション」

以下のコマンドで、ソケットの動作をテストできます。

shell> mysqladmin --socket=/path/to/socket version

A.4.6. タイムゾーンの問題

SELECT NOW() が現地時間ではなく GMT の値を返す場合、現在のタイムゾーンに TZ 環境変数を設定する必要があります。サーバが動作している環境(たとえば mysqld_safe または mysqld_safe)に対して設定を行ってください。 See 付録?F. 環境変数

A.5. クエリ関連の問題

A.5.1. 検索時のケース依存

デフォルトでは、MySQL 検索では大文字と小文字は区別されませんが(ケース非依存)、中には、ケース依存のキャラクタセット(czech)もあります。 つまり、col_name LIKE 'a%' で検索すると、A または a で始まる全カラムの値が検出されます。これをケース依存にする場合は、INSTR(col_name, "A")=1 としてプリフィックスをチェックします。または、カラム値が確実に "A" でなければならない場合は、STRCMP(col_name, "A") = 0 を使用します。

簡単な比較演算(>=、>、=、<、<=、ソートおよびグループ化)は、各文字の ``ソート値'' に基づいています。同じソート値のある文字(E、e および e など)は、同じ文字として扱われます。

旧 MySQL バージョンでは、LIKE 比較は、各文字の大文字の値(E == e but E <> e)で実行されました。新しい MySQL バージョンでは、LIKE は他の比較演算と同じように動作します。

カラムを常にケース依存で扱う場合は、BINARY として宣言します。 See 項6.5.3. 「CREATE TABLE 構文」

Big5 と呼ばれるエンコードで中国語データを使用している場合、すべての文字カラムを BINARY にします。Big5 エンコード文字のソート順序は ASCII コードの順序に基づいているため、これが機能します。

A.5.2. DATE カラム使用時の問題

DATE 値の書式は 'YYYY-MM-DD' です。標準 SQL では、他の書式は使用できません。この書式は、UPDATE 式と SELECT ステートメントの WHERE 節で使用してください。たとえば、以下のように使用します。

mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';

日付が数値コンテキストで使用されている場合は、利便性を考えて、MySQL は日付を数値に自動的に変換します(逆の場合も同様です)。更新時や WHERE 節で ``柔軟な'' 文字列書式を使用できるので、日付を TIMESTAMPDATE または DATETIME カラムと比較することもできます(柔軟な書式とは、どんな句読文字もパート間の区切り記号として使用できる書式のことを言います。たとえば、'1998-08-15''1998#08#15' は同一です)。また MySQL は、区切り記号を含まない文字列(たとえば '19980815')も、それが日付として理解できる場合は変換することができます。

特別な '0000-00-00' 日付は、'0000-00-00' として格納し取り出すことができます。MyODBC を介して '0000-00-00' 日付を使用している場合、MyODBC バージョン 2.40.12 以上では自動的に NULL に変換されます。

MySQL は上述の変換を実行するため、以下のステートメントを使用します。

mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');

mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT MOD(idate,100) FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';

ただし、以下は動作しません。

mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;

STRCMP() は文字列関数なので、idate が文字列に変換され、文字列比較が実行されます。'19970505' は日付に変換されず、日付比較も実行されません。

MySQLは、日付が正しいかどうかという非常に限定された確認しか行いません。'1998-2-31' のような不正な日付を格納すると、間違った日付が格納されます。

MySQL は、日付を圧縮して保存するため、結果バッファに適合しない特定の日付は格納できません。日付の受け入れ規則は、以下のとおりです。

  • MySQL が任意の日付を格納し取り出せる場合、DATEDATETIME カラムは間違った日付を受けつける。

  • 0 ? 31 のすべての値は、どんな日付にも受け入れられる。これは、3 つの別々のフィールドで年、月、日を保存する Web アプリケーションでは非常に便利である。

  • 日または月フィールドをゼロにすることもできる。これは、DATE カラムに生年月日を格納する場合で、日付の一部しか知らないときに便利である。

日付を適切な値に変換できない場合は、0DATE フィールドに格納され、0000-00-00 として取り出されます。データベースが行うことは、ユーザが格納した日付と同じものを取り出すことなので(日付が論理的に正しくない場合でも)、これはスピードと利便性両方の問題になります。 我々は、日付を確認するのはサーバではなくアプリケーションの責任であると考えています。

A.5.3. NULL 値の問題

NULL 値というものを SQL 初心者はよく混乱します。SQL 初心者は、多くの場合、NULL が空文字 "" と同じであると考えてしまいます。これは違います。たとえば、以下のステートメントは完全に別のものです。

mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ("");

どちらのステートメントも、値を phone カラムに挿入しています。しかし、最初のステートメントは NULL 値を挿入し、2 つ目は空文字を挿入しています。最初のステートメントは ``電話番号が不明'' であると考えることができ、2番目は``電話を持っていない'' と考えることができます。

SQL では、NULL 値は、他の値と比較すると(NULLでも)常に偽になります。NULL を含む式は、演算子と式に含まれている関数のドキュメントに特に断りがなければ、常に NULL 値を生成します。以下の例では、全カラムが NULL を返します。

mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);

NULL のカラム値を検索したい場合、=NULL テストは使用できません。どんな式でも expr = NULL は偽なので、以下のステートメントはレコードを返しません。

mysql> SELECT * FROM my_table WHERE phone = NULL;

NULL 値を検出するには、IS NULL テストを使用します。 以下から、NULL の電話番号と空の電話番号の検索方法がわかります。

mysql> SELECT * FROM my_table WHERE phone IS NULL;
mysql> SELECT * FROM my_table WHERE phone = "";

MySQL バージョン 3.23.2 以降を使用し、かつ MyISAMInnoDBBDB テーブル型を使用している場合に限り、NULL 値を持つことができるカラムのインデックスを追加することができます。 以前のバージョンや別のテーブル型では、NOT NULL などのカラムを宣言する必要があります。これは、NULL をインデックス化されたカラムに挿入できないということでもあります。

LOAD DATA INFILE でデータを読み取ると、空のカラムは '' で更新されます。カラムに NULL 値が必要な場合は、テキストファイルで \N を使用してください。状況によっては、リテラル文字 'NULL' も使用されます。 See 項6.4.8. 「LOAD DATA INFILE 構文」

ORDER BY を使用する際、降順でソートするように DESC を指定すると、NULL 値が最初または最後に表示されます。例外: MySQL バージョン 4.0.2 から 4.0.10 では、ソート順序に関わらず NULL 値は 1 番目にソートされます。

GROUP BY を使用すると、すべての NULL 値が同じと見なされます。

COUNT()MIN()SUM() などの集約(要約)関数では、NULL 値は無視されます。例外は COUNT(*) です。この関数は、個々のカラム値ではなくレコードをカウントします。 たとえば、以下のステートメントでは 2つのカウントが行われます。 最初は、テーブルにあるレコード数のカウントです。2 番目は age カラムにある非 NULL 値のカウントです。

mysql> SELECT COUNT(*), COUNT(age) FROM person;

NULL 処理を補うために、IS NULLIS NOT NULL 演算子と IFNULL() 関数を使用することができます。

カラム型の中には、NULL 値が特別に扱われるものがあります。テーブルの最初のカラム TIMESTAMPNULL を挿入すると、現在の日付と時刻が挿入されます。AUTO_INCREMENT カラムに NULL を挿入すると、順番の次の番号が挿入されます。

A.5.4. alias の問題

エイリアスを使用して、GROUP BYORDER BY または HAVING 部分のカラムを参照することができます。エイリアスを使用して、カラムにわかりやすい名前を付けることもできます。

SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
SELECT id AS "Customer identity" FROM table_name;

標準 SQL では、WHERE 節のエイリアスを参照することはできません。これは、WHERE コードが実行される際、カラム値がまだ設定されていない場合があるためです。たとえば、以下のクエリは無効です。

SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;

WHERE ステートメントを実行して GROUP BY 部分に追加するレコードを決定し、HAVING を実行して結果セットからどのレコードを使用するか決定します。

A.5.5. 関連テーブルからのレコードの削除

MySQL では、サブクエリをサポートしていません(バージョン 4.1 より前)。また、DELETE ステートメントでの 2 つ以上のテーブルの使用もサポートしていません(バージョン 4.0 より前)。そのため、2 つの関連テーブルからレコードを削除するには、以下の方法を使用してください。

  1. メインテーブルで WHERE 条件に基づいて、レコードを SELECT する。

  2. 同じ条件に基づいて、メインテーブルのレコードを DELETE する。

  3. DELETE FROM related_table WHERE related_column IN (selected_rows)

related_column のクエリの合計文字数が 1,048,576(max_allowed_packetのデフォルト値)を超える場合、分割して、複数回 DELETE ステートメントを実行してください。related_column がインデックスの場合は、100 ? 1000 の related_column ID を削除するだけなので、通常 DELETE が非常に速くなります。related_column がインデックスでない場合、速度は IN 節の引数の数に依存しません。

A.5.6. 不整合レコードの問題解決

多くのテーブルが含まれる複雑なクエリを使用していて、それがレコードを返さない場合、以下の手順でクエリの問題を見つける必要があります。

  1. EXPLAIN でクエリをテストし、明らかに問題と思われる箇所があるか確認する。 See 項5.2.1. 「EXPLAIN 構文(SELECT に関する情報の取得)」

  2. WHERE 節で使用されるフィールドだけを選択する。

  3. レコードが返るまで、クエリから 1 つ 1 つテーブルを削除する。 テーブルが大きい場合に有効なのは、クエリで LIMIT 10 を使用する方法である。

  4. クエリから最後に削除されたテーブルに対してレコードが一致したカラムに、 SELECT を実行する。

  5. FLOAT または DOUBLE カラムを小数と比較している場合、'=' は使用できない。浮動小数点の値は正確な値ではない。この問題は大部分のコンピュータ言語で共通。 たいていの場合、FLOATDOUBLE に変更すると問題は解決する。 See 項A.5.7. 「浮動小数点比較の問題」

  6. それでも問題が解決できない場合は、mysql test < query.sql で実行できる小さなテストを作成して、問題を表示する。 mysqldump --quick database tables > query.sql で、テストファイルを作成できる。エディタでファイルを開き、数が多ければいくつかの挿入行を削除する。そして、ファイルの最後に SELECT ステートメントを追加する。

    まだ問題が残っているかどうか、以下の方法でテストしてください。

    shell> mysqladmin create test2
    shell> mysql test2 < query.sql
    

    mysqlbug を使用して、テストファイルを汎用 MySQL メーリングリストに投稿してください。 See 項1.7.1.1. 「MySQL メーリングリスト」

A.5.7. 浮動小数点比較の問題

浮動小数点数は、コンピュータアーキテクチャ内部では正確な値として格納されないため、混乱を引き起こす場合があります。通常画面に表示される値は、正確な値ではありません。

フィールドタイプ FLOATDOUBLE、および DECIMAL が該当します。

CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
(6, 0.00, 0.00), (6, -51.40, 0.00);

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

結果は正確です。最初の 5 つのレコードは比較テストにパスしないように見えますがパスできます。コンピュータアーキテクチャによりますが、数の差異は、小数点第 10 位くらいで現れるためです。

結果は浮動小数点数なので、ROUND( )(または同様の関数)を使用して問題を解決することはできません。たとえば、以下のとおりです。

mysql> SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

カラム 'a' 内の数は以下のようになります。

mysql> SELECT i, ROUND(SUM(d1), 2)*1.0000000000000000 AS a,
    -> ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i HAVING a <> b;
+------+----------------------+-------+
| i    | a                    | b     |
+------+----------------------+-------+
|    1 |  21.3999999999999986 | 21.40 |
|    2 |  76.7999999999999972 | 76.80 |
|    3 |   7.4000000000000004 |  7.40 |
|    4 |  15.4000000000000004 | 15.40 |
|    5 |   7.2000000000000002 |  7.20 |
|    6 | -51.3999999999999986 |  0.00 |
+------+----------------------+-------+

コンピュータアーキテクチャによって、同じ結果が表示されたりされなかったりします。 CPU ごとに浮動小数点数の評価方法が異なります。たとえばマシンの中には、両方の引数を 1 で掛け合わすと '正確な' 結果を得られるものがあります。たとえば以下のようになります。

警告: あなたのアプリケーションでは、この方法を決して信用しないでください。これは間違った方法の例です。

mysql> SELECT i, ROUND(SUM(d1), 2)*1 AS a, ROUND(SUM(d2), 2)*1 AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+

上記の例が動作するように見える理由は、テストが実行されたマシンで、CPU 浮動小数点演算が複数の数字を偶然同じ数字に四捨五入してしまうことにあります。しかし、CPU がそうしなければならないという規則はないため、この例は信用できません。

浮動小数点数比較を行う正しい方法は、まず数の許容範囲を決定し、続いて許容範囲の数に対して比較を行うことです。たとえば、浮動小数点数は同一と見なすということにすれば、それらが 10000 分の 1(0.0001)の精度で同じである場合、比較が以下のように行われます。

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+
1 row in set (0.00 sec)

逆に、数が同じになるレコードを取得したい場合は、テストは次のようになります。

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) < 0.0001;
+------+-------+-------+
| i    | a     | b     |
+------+-------+-------+
|    1 | 21.40 | 21.40 |
|    2 | 76.80 | 76.80 |
|    3 |  7.40 |  7.40 |
|    4 | 15.40 | 15.40 |
|    5 |  7.20 |  7.20 |
+------+-------+-------+

A.6. オプティマイザ関連の問題

MySQL はオプティマイザを使用して、クエリを解決する最も優れた方法を見つけ出します。多くの場合、MySQL は最も可能性のあるクエリを見積もることができますが、場合によってはデータに関する十分な情報が手元にないので、経験に基づく '推測' を行う必要があります。

ここでは、MySQL が正しく理解しない場合を扱います。

MySQL が '正しく' 最適化するのに役立つツールは、以下のとおりです。

A.6.1. テーブルスキャンを回避する方法

MySQL がテーブルスキャンを使用してクエリを解決した場合、EXPLAIN では type カラム内に ALL が表示されます。これは、通常以下の場合に起こります。

  • テーブルが小さく、キー走査よりもテーブルスキャンを行う方が速い場合。 これは、レコードの数が 10 未満で、レコードの長さが短いテーブルではよくあるケースである。

  • ON または WHERE 節に、インデックスを張ったカラムを利用する条件がない場合。

  • インデックスを張ったカラムと変数を比較中に、MySQL が(インデックスツリーに基づいて)、変数がテーブルの大部分の範囲に及んでいるためテーブルスキャンの方が速いと予測した場合。 See 項5.2.4. 「MySQL による WHERE 節の最適化」

  • 別のカラムを介して、下位の基数(= 多くの一致レコード)でキーを使用している場合。この場合、MySQL は、そのキーを使用して多くのキールックアップが行われると見なし、テーブルスキャンの方が早いと見なす。

大きなテーブルの '不正な' テーブルスキャンを回避するには、以下のことを行います。

  • スキャンテーブルに対して ANALYZE TABLE を使用し、キーの分布を更新する。 See 項4.6.2. 「ANALYZE TABLE 構文」

  • スキャンテーブルに対して FORCE INDEX を使用し、テーブルのスキャンは、特定のインデックスの使用と比較すると非常に処理の負荷が高いことを、MySQL に通知する。 See 項6.4.1. 「SELECT 構文」

    SELECT * FROM t1,t2 force index(index_for_column) WHERE t1.column=t2.column;
    
  • --max-seeks-for-key=1000 を指定して mysqld を起動するか SET MAX_SEEKS_FOR_KEY=1000 を行って、オプティマイザに、キースキャンで 1000 を越すキー検索が行われないことを告げる。

A.7. テーブル定義関連の問題

A.7.1. ALTER TABLE の問題

ALTER TABLE によって、テーブルが現在のキャラクタセットに変更されます。 ALTER TABLE 中に duplicate key error が発生する場合、新しいキャラクタセットが 2 つのキーを同じ値にマップしているか、テーブルが壊れています。テーブルが壊れている場合は、そのテーブルで REPAIR TABLE を実行してください。

以下のようなエラーで ALTER TABLE が強制終了される場合

Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)

原因として、MySQL が前回の ALTER TABLE でクラッシュしており、使用されていない A-something または B-something という名前の古いテーブルがあることが考えられます。この場合、MySQL データディレクトリに移り、A- または B- で始まる名前のファイルをすべて削除してください(削除しないで別の場所に移動することもできます)。

ALTER TABLE は、以下のように動作します。

  • 変更要求のあった A-xxx という名前の新しいテ-ブルを作成する。

  • 旧テーブルのすべてのレコードが A-xxx にコピーされる。

  • 旧テーブル名が B-xxx に変更される。

  • A-xxx が旧テーブル名に変更される。

  • B-xxx が削除される。

名前変更操作に何か問題が発生した場合は、MySQL は変更を取り消します。致命的な問題が発生した場合(もちろん起こってはならないことですが)、MySQL は旧テーブルを B-xxx のままにしておく可能性がありますが、システムレベルでの簡単な名前変更でデータは元に戻ります。

A.7.2. テーブルのカラム順序を変更する方法

SQL の主な目的は、データストレージから要求した情報を抽出することです。必ず、データを取り出す順序を指定する必要があります。たとえば、以下のようになります。

SELECT col_name1, col_name2, col_name3 FROM tbl_name;

上記は、col_name1col_name2col_name3 の順序でカラムを返します。

SELECT col_name1, col_name3, col_name2 FROM tbl_name;

上記の場合、col_name1col_name3col_name2 の順序でカラムを返します。

カラム順序は、以下のように変更できます。

  1. 正しい順序のカラムで新しいテーブルを作成する。

  2. INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table を実行する。

  3. old_table を廃棄するか、名前変更する。

  4. ALTER TABLE new_table RENAME old_table

カラムを追加、移動、削除する場合、カラムが返される順序と位置が同じにならないので、アプリケーションで、SELECT * を使用してその位置に依存するカラムを絶対に取り出さないでください。データベース構造に簡単な変更を加えるだけでも、アプリケーションエラーが発生します。 もちろん SELECT * は、クエリのテストに最適です。

A.7.3. テンポラリテーブルの問題

以下、テンポラリテーブルの制限を示します。

  • テンポラリテーブルの型は、HEAPISAMMyISAMMERGEInnoDB のみ。

  • テンポラリテーブルは同じクエリで 2 回以上使用できない。 たとえば、以下は動作しない。

    mysql> SELECT * FROM temporary_table, temporary_table AS t2;
    
  • TEMPORARY テーブルで RENAME は使用できない。 ALTER TABLE org_name RENAME new_name は使用できる。


This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.

アダルトレンタルサーバー