カテゴリー
SQL

MySQLでDumpをリストアするときにメモリ不足のエラーが出たとき

Dumpファイルをリストアしようとすると、メモリ不足のエラーでリストアできなかった。

リストア先のmax_allowed_packetとnet_buffer_lengthが足りていなかった模様。

 

リストア先のサーバパラメータを変更しても良いが、Dump取得時(Dumpファイル作成時)に以下のようなパラメータを設定すれば、Dump内容をリストア先サーバーのメモリに合わせておくことができるのでリストア時のメモリ不足を回避できる。

mysqldump -u [MYSQL_USER] –opt –pass=[LOGIN_PASS] -h[SRC_HOST] –net_buffer_length=16k –max_allowed_packet=134217728 [SRC_DB] [SRC_TABLE] > [./TOFILE.sql(destination)]

カテゴリー
SQL

MySQL+Spiderがクラッシュした際の復活方法

MySQL+Spiderの組み合わせで運用している場合、Spiderノードがメモリ不足によりクラッシュする場合がある。
よくある。とくにシステム構築中のテスト稼働や大量データの移行時、パラメータチューニング中など…。

ところがこれが発生すると、通常のrestartやstop~startが効かなくなる。
sockが無いとか、pid fileが腐ってると言われたりして、まったくMySQL起動しなくなる。

そんな時の解決方法として下記手段を用いているが、それでも復活しない場合もある...。

1.まずはsockファイルを作成

vi /tmp/mysql.sock

内容はブランクでよいので、このまま保存してviを閉じる。

2.pidファイルを作成
pidファイルが無くなっているか腐っている場合が多いので、こちらもブランクのファイルを作成。
パスやpidファイル名は適宜変更。
(startする際にpidファイルに関するエラーメッセージが表示されるので、エラーメッセージに表示されるpidファイル名を利用するとよい)

vi /where/you/install/mysql/data/ip-999-999-999-999.pid

3.上記で作成したファイルの権限を変更

chown mysql:mysql /tmp/mysql.sock
chown mysql:mysql /where/you/install/mysql/data/ip-999-999-999-999.pid

4.mysqld_safeを起動させ、その間にmysqldをスタート
ターミナルを2つ用意して、まずはmysql_safeを起動。

/where/you/install/mysql/bin/mysqld_safe

その間に別のターミナルでMySQLサーバを起動します。

service mysql start

これで起動するときがあります。
それでも無理な時はサーバを窓から投げ捨ててください...。

歴戦のDBAとかではないのでこのような対処療法しか知りません。
どなたか、もっと良い方法をご存知の方は是非教えていただきたい。

カテゴリー
SQL

ツリーの閉包モデル リーフの移動、追加で自分への補足 「SQLアンチパターン」より

1月にオライリー・ジャパンより「SQLアンチパターン」が発売されました。
この本で紹介されているツリー構造をRDBMSで扱う手法の一つ「閉包モデル」は初めて知ったのですが、最後の方に出てくるpath_lengthを追加した場合のSQLが掲載されていなかったので、自分のために補足として書き残しておきます。

以下は本に掲載されているリーフを追加する際のSQLですが…

INSERT INTO TreePaths (ancestor, descendant)
SELECT t.ancestor, 8
FROM TreePaths AS t
WHERE t.descendant = 5
UNION ALL
SELECT 8, 8;

このままではpath_lengthが追加されません。
そこで、以下のようにサブクエリ部分のフィールドで既存レコードのpath_lengthに+1して返すようにすれば、追加されるリーフのpath_lengthは自動で計算されることになります。

INSERT INTO TreePaths (ancestor, descendant, path_length)
SELECT t.ancestor, t.path_length + 1, 8
FROM TreePaths AS t
WHERE t.descendant = 5
UNION ALL
SELECT 8, 8;

また、リーフを移動する際のSQLは以下のように掲載されていますが…

INSERT INTO TreePaths (ancestor, descendant)
SELECT supertree.ancestor, subtree.descendant
FROM TreePaths AS supertree
CROSS JOIN TreePaths AS subtree
WHERE supertree.descendant = 3
AND subtree.ancestor = 6;

これを以下のようにサブクエリ部分のフィールドでsupertree.path_length + subtree.path_length + 1を返せば、自動的にpath_lengthが計算された状態でリーフが移動されます。

INSERT INTO TreePaths (ancestor, descendant,path_length)
SELECT supertree.ancestor, subtree.descendant, supertree.path_length + subtree.path_length + 1
FROM TreePaths AS supertree
CROSS JOIN TreePaths AS subtree
WHERE supertree.descendant = 3
AND subtree.ancestor = 6;

以上、試してないけど、たぶんこれでいけるはず。