web-dev-qa-db-ja.com

MySQLが複数の結合を行う際のtmpテーブルの不正なキーファイル

私は頻繁に助けを求めてここに来ることはありませんが、これにはかなり不満を感じています。

複数の結合を使用してテーブルからレコードをフェッチしようとするたびに、このエラーが発生します。

#126 - Incorrect key file for table '/tmp/#sql_64d_0.MYI'; try to repair it

したがって、このクエリはエラーを生成します。

SELECT * FROM `core_username`
INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
ORDER BY `core_username`.`name` ASC LIMIT 1

しかし、これはしません:

SELECT * FROM `core_username`
INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
ORDER BY `core_username`.`name` ASC LIMIT 1

そして、これもそうではありません:

SELECT * FROM `core_username`
INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
ORDER BY `core_username`.`name` ASC LIMIT 1

これは何が原因ですか? tmpテーブルを修復する方法を実際には知りませんが、毎回新しいtmpテーブルであるため、それが問題だとは本当に思いません。ユーザー名テーブルはかなり大きい(現在233,718レコード)が、それとは何の関係もないと思う。

どんな助けでも大歓迎です。

[〜#〜] update [〜#〜]:さらにテストした結果、結果を並べようとするとエラーが発生するようです。つまり、このクエリは私が期待するものを提供します:

SELECT * FROM `core_username`
INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
LIMIT 1

しかし、私が追加した場合:

ORDER BY `core_username`.`name` ASC

エラーがトリガーされます。これは、現在使用している特定のWebサーバーでのみ発生します。データベースをダウンロードして、ローカルホストと他のサーバーで同じことを試してみると、問題なく動作します。 MySQLバージョンは5.0.77です。

これを知っているので、作成中のtmpテーブルが大きすぎて、MySQLが窒息しているということがかなり確信しています このブログ投稿で説明されているように 。しかし、解決策がどうなるかはまだわかりません...

57

一時テーブルでこのエラーが発生する場合があります。

#126 - Incorrect key file for table '/tmp/#sql_64d_0.MYI'; try to repair it

/tmpフォルダーの容量が不足している可能性があります。一部のLinuxインストールでは、/tmpは独自のパーティションにあり、スペースがあまりありません-大きなMySQLクエリでいっぱいになります。

df -hを使用して、\tmpが独自のパーティションにあるかどうか、および割り当てられているスペースの量を確認できます。

独自のパーティションにあり、スペースが不足している場合は、次のいずれかを実行できます。

(a)/ tmpを変更して、パーティションのスペースを増やします(メインパーティションに再割り当てまたは移動することにより、たとえば こちらを参照
(b)MySql構成を変更して、異なるパーティションで 異なるtemp folder を使用するようにします。 /var/tmp

102
codeulike

大きなテーブルで作業しているときに数百MBを消費する可能性があるため、クエリの実行中にMySQLのtmpdirの空き容量(この場合は/ tmp)を確認します。このような何かが私のために働いた:

$ while true; do df -h /tmp; sleep .5; done
20
Francesc Rosàs

これを実行する

REPAIR TABLE `core_username`,`core_site`,`core_person`;

またはこれを行う:

select * from (
 SELECT * FROM `core_username`
 INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
 INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
 LIMIT 1)
ORDER BY `name` ASC
6
Pentium10

「ANALYZE TABLE」の実行が役立つ場合があります。

この問題は大きなテーブル(〜1億行)で突然発生し、MySQLは/ tmpを使用して1GBを超える一時テーブルを書き込もうとしましたが、/ tmpが〜600Mに制限されていたため失敗しました。

InnoDBテーブルの統計はかなり古いことが判明しました。 「ANALYZE TABLE ...」を実行すると、統計が更新され、問題が解決しました。より正確な統計により、MySQLはクエリを正しく最適化することができ、大きなtmpファイルは必要なくなりました。

「mysqlcheck -Aa」を定期的に実行して、すべてのテーブル統計を最新に保ちます。

4
Roger Lucas

500K以上のレコードがあるテーブルでクエリを実行すると、この問題が発生しました。/tmpディレクトリにある.MYIファイルを指し、チェック時にめったにそこになかった同じタイプのエラーを私に与えていました。 /etc/my.cnfファイルのヒープと一時ファイルのサイズをすでに増やしていました。

クエリの問題は、最後にORDER句が実際に含まれていたため、クエリを省略するとエラーなく動作することでした。また、制限がありました。テーブル内の最新の5つのレコードを調べようとしました。 ORDER句を含めると、それが詰まってエラーが発生しました。

何が起こっていたのかというと、mysqldは、ORDERを適用するために、巨大テーブルのすべてのレコードを含む内部一時テーブルを作成していました。

これを回避する方法は、追加のWHERE条件を適用して、巨大なテーブルのレコードをより小さなセットに制限することです。都合の良いことに、フィルタリングを行う日時フィールドがありました。

私はそれが誰かを助けることを願っています。

3
ClickWhisperer

Unixでは、MySQLは一時ファイルを保存するディレクトリのパス名としてTMPDIR環境変数の値を使用します。 TMPDIRが設定されていない場合、MySQLはシステムのデフォルトを使用します。通常は/ tmp、/ var/tmp、または/ usr/tmpです。

Windows、Netware、およびOS2では、MySQLはTMPDIR、TEMP、およびTMP環境変数の値を順番にチェックします。最初に設定されたものについては、MySQLはそれを使用し、残りをチェックしません。 TMPDIR、TEMP、またはTMPのいずれも設定されていない場合、MySQLはWindowsシステムのデフォルト(通常はC:\ windows\temp)を使用します。

一時ファイルディレクトリを含むファイルシステムが小さすぎる場合は、mysqldの--tmpdirオプションを使用して、十分なスペースがあるファイルシステムのディレクトリを指定できます

MySQL 5.0では、-tmpdirオプションをラウンドロビン方式で使用されるいくつかのパスのリストに設定できます。パスは、Unixではコロン文字(「:」)、Windows、NetWare、およびOS/2ではセミコロン文字(「;」)で区切る必要があります。

2
Jaydeep Dave

同じ問題が発生します。

私の解決策は次のとおりです。1.「select *」を使用しないでください。必要なフィールドを選択するだけです。 2.クエリを分割します。選択したフィールドが多すぎる場合、それをクエリに分割すると結果になる可能性があります。結果を含む変数を変更しない場合は、後で結果を「array_merge()」できます。

私の場合、クエリを5つのクエリに分割し、PHPを使用して配列をマージします。

問題はmysqlサーバーにあります。それは、アプリケーション開発者(私たちなど)が優先権を持たないことです。

1
Ahmad

同様の問題がありました。私の場合、間違った所有者/許可が原因で問題が発生しました。データディレクトリの所有者をmysqlユーザーに変更するだけで問題は解決しました。

0
Lateef
0
DarckBlezzer