MySQLにgdbアタッチするメモ
MySQLにgdbアタッチしてソースコードからいろいろ追う方法を教わったので自分メモ。
- gdbアタッチ
gdb -p mysqldのプロセス番号
この時点でmysqldが一時停止される。
- ブレイクポイント
(gdb) b function_name
- mysqld再開
(gdb) c
- ステップ実行
(gdb) n
- 変数確認
(gdb) p 変数名 (gdb) display 変数名
- thread確認
(gdb) thread apply all bt (gdb) frame スレッド番号 (gdb) bt
その他
- innodb_prefixのサーバ変数は
ha_innodb.cc
を見る。あとは変数名をもとに関数のあたりをつける。 print do_command::thd->query_string.string.str
クエリ確認。- ファイルディスクリプター
/proc/プロセス番号/fd
やlsof -p プロセス番号
で確認してstraceで追うstrace -f -e write,open -p プロセス番号 2>&1 | egrep -v 'write\(4[01], '
みたいな。
追記 20190530
MySQL5.7以降ぐらいからクエリ確認方法は
print do_command::thd->m_query_string
文字列が削られる場合はをつける
set print elements 0
Oracle SEでの運用いろいろ@JPOUG in 15 minutes #1
JPOUG in 15 minutes #1 | Japan Oracle User Group (JPOUG)で自分がやってきたOracle SEでの運用方法について話をさせてもらいました。
www.slideshare.net
主な話としてはSEでASHっぽく分析する仕組みを作った話だったのですが、
使用したツールはMySQLでデータストアしてMUNINでグラフ化なんですが確実に最近の流行りな方法ではないです。。w
あとは、最後にちょこっとご指摘いただいた
本番のOracle側でSQLを実行してるのか、セッション情報をストアしてるMySQL側でSQL実行しているか説明不足でしたので追記しました。
人に説明するのはやっぱり難しいなと痛感しました。
ともかく、今回でJPOUGで3回も登壇させてもらったのでSEネタの持ちカードはもうないっっ。。
MyDumperを使ってみた
MySQLのデータインポートツールMyDumper
を試したのでメモ。
- mysqldump・・・データのエクスポート・インポートをシングルスレッドで実行
- mydumper・・・データのエクスポート・インポートをパラレルスレッドで実行
エクスポートしたファイルごとにパラレルで実行する。デフォルトはテーブル単位でパラレル化。
巨大なテーブルがあればデータをチャンクごとに分けファイルを分散することで高速に実行してくれる。
インストール
- yumでインストール
yum install https://twindb.com/twindb-release-latest.noarch.rpm yum install mydumper
- 確認
$ mydumper --version mydumper 0.6.2, built against MySQL 5.6.25
もし、libmysqlclient.so.18
がないよ。って言われた場合はyumでMySQL5.6をインストール(5.1ではだめ)。
または、libmysqlclient.so.18
がある場所にLD_LIBRARY_PATH
で設定。
コマンド
- mydumper・・・export用コマンド
- myloader・・・import用コマンド
試す
DB容量:280G(内130Gが1つのテーブル)
export DB設定
- MySQL5.6
- stop slaveして実行する
import DB設定
EXPORT
- 10スレッドでGZ圧縮してチャンクサイズ10000000行で取得。
注意:exportはスキーマの指定はフルまたは1つのスキーマになってしまうので複数スキーマを指定することはできない。
-Tオプションでテーブル単位で指定可能。information_schema.tables
で複数のスキーマから取得する方法を教わったのでそちらで実行。
time mydumper -u root -p 'xxxxxxx' -S /var/lib/mysql/mysql.sock -e -t 10 -c -o /tmp/dump_dir -r 10000000 -s 5000000 -T $(mysql -sse"set group_concat_max_len=10240; select aa from (select 1,group_concat(concat(table_schema,'.',table_name)) as aa from information_schema.tables where table_schema in ('main','sub1','sub2','sub3','sub4') group by 1) a") real 43m41.139s user 220m16.990s sys 3m0.312s
約44分
- 1スレッドかつチャンク分けなしでやった場合は約4時間20分かかった。
出力ファイル確認
できたファイルはこんな感じで分かれている。
$ ls -ltr /tmp/dump_dir 合計 45721788 ・ ・ -rw-rw-r-- 1 mysql mysql 679 6月 1 16:00 2016 main.table1.sql.gz -rw-rw-r-- 1 mysql mysql 169 6月 1 16:00 2016 main.table2.sql.gz -rw-rw-r-- 1 mysql mysql 185 6月 1 16:00 2016 main.table3.sql.gz -rw-rw-r-- 1 mysql mysql 76932 6月 1 16:00 2016 main.table4.sql.gz -rw-rw-r-- 1 mysql mysql 208327 6月 1 16:00 2016 main.table5.sql.gz -rw-rw-r-- 1 mysql mysql 1505960 6月 1 16:00 2016 sub1.subtable1.sql.gz -rw-rw-r-- 1 mysql mysql 768276450 6月 1 16:06 2016 sub1.subtable2.00000.sql.gz -rw-rw-r-- 1 mysql mysql 750226866 6月 1 16:06 2016 sub1.subtable2.00001.sql.gz -rw-rw-r-- 1 mysql mysql 770132442 6月 1 16:07 2016 sub1.subtable2.00002.sql.gz
通常はテーブル単位でのファイルだが、チャンク分けしていると連番でファイルも分かれている。
- スレーブとして起動したい場合は
metadata
ファイルを確認するとポジション情報が記載してある
$ vim /tmp/dump_dir/metadata 1 Started dump at: 2016-06-01 16:00:13 2 SHOW MASTER STATUS: 3 Log: mysql-bin.000275 4 Pos: 120 5 6 SHOW SLAVE STATUS: 7 Host: 192.168.1.2 8 Log: mysql-bin.000438 9 Pos: 944084446 10 11 Finished dump at: 2016-06-01 16:39:00
IMPORT
- 16スレッドで実行
$ time myloader -d /tmp/dump_dir -u root -p 'xxx' -S /var/lib/mysql/mysql.sock -t 16 real 525m31.015s user 299m14.828s sys 3m8.467s
約8時間45分
- チャンク分けなしのものを16スレッドで実行した場合。 結局全DB量の半分近くを占めているテーブルがシングル実行になるので遅い。
$ time myloader -d /tmp/dump_dir -u root -p 'xxx' -S /var/lib/mysql/mysql.sock -t 16 real 1541m14.572s user 245m43.989s sys 2m23.104s
約25時間
よって、チャンク分けをうまくすればmydumper結構使える。
注意
- ibdata1のサイズが大きくなる。
50%はinsert bufferが占めていた。セカンダリインデックスを後で貼るようにしてくれたらいいのにな。
*8.1G* 6月 3 01:01 2016 ibdata1 こうなるので注意。
OEM再作成のエラー対処方法
RMANで別ホストに移行した時にOEMの作成でいろいろ嵌ったのでメモ。
emca -config dbcontrol db -repos recreate実行時
パターン1
設定: ORA-01031: ???????-?????????? ・ ・ ・ 2014/10/09 9:58:40 oracle.sysman.emcp.util.GeneralUtil initSQLEngineLoacly 設定: SQLEngine created successfully and connected 2014/10/09 9:58:40 oracle.sysman.emcp.ParamsManager checkListenerStatusForDBControl 設定: ORA-01031: ???????-?????????? 2014/10/09 9:58:40 oracle.sysman.emcp.EMConfig perform 情報: この操作は/opt/app/oracle/cfgtoollogs/emca/orcl/emca_2014_10_09_09_57_46.logでロギングされています。 2014/10/09 9:58:40 oracle.sysman.emcp.EMConfig perform 致命的: リスナーが起動していないか、データベース・サービスがリスナーに登録されていません。リスナーを起動し、データベース・サービスを登録し、EM Configuration Assistantを再度実行してください。 詳細は、/opt/app/oracle/cfgtoollogs/emca/orcl/emca_2014_10_09_09_57_46.logにあるログ・ファイルを参照してください。 構成を完了できませんでした。 詳細は、/opt/app/oracle/cfgtoollogs/emca/orcl/emca_2014_10_09_09_57_46.logにあるログ・ファイルを参照してください。
- 設定: ORA-01031: ???????-??????????→権限が不足しているエラー
- パスワードファイルがなかったのでをコピーまたは作成してあげて再実行
パターン2
・ ・ 2014/10/14 18:59:33 oracle.sysman.emcp.ParamsManager getLocalListener 警告: oracle-test-dbのリスナーを取得中にエラーが発生しました 2014/10/14 18:59:37 oracle.sysman.emcp.util.DBControlUtil secureDBConsole 情報: Database Controlの保護中(少し時間がかかります)... ・ ・
- listener.oraからデフォルトリスナーLISTENER(1521)の記述がなかった。
パターン3
2014/10/14 18:59:37 oracle.sysman.emcp.util.DBControlUtil secureDBConsole 情報: Database Controlの保護中(少し時間がかかります)... 2014/10/14 18:59:41 oracle.sysman.emcp.util.PlatformInterface executeCommand 警告: /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl secure dbconsole -host oracle-test-db -sid orcl の実行中のエラ ー 2014/10/14 18:59:41 oracle.sysman.emcp.EMDBPostConfig performConfiguration 警告: Database Controlの保護中にエラーが発生しました。 2014/10/14 18:59:41 oracle.sysman.emcp.EMDBPostConfig setWarnMsg 情報: Database Controlの保護中にエラーが発生しました。Database Controlが非セキュア・モードで起動されています。Database Controlを保護するには、次のコマンドを実行してください。 1) 環境変数ORACLE_UNQNAMEを一意のデータベース名に設定します 2) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl stop dbconsole 3) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl config emkey -repos -sysman_pwd < SYSMANユーザーのパスワード > 4) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl secure dbconsole -sysman_pwd < SYSMANユーザーのパスワード > 5) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl start dbconsole EMキーを保護するには、/opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl config emkey -remove_from_repos -sysman_pwd < SYSMANユーザーのパスワード >を実行します 2014/10/14 18:59:41 oracle.sysman.emcp.util.DBControlUtil startOMS 情報: Database Controlの起動中(少し時間がかかります)... 2014/10/14 18:59:51 oracle.sysman.emcp.EMDBPostConfig performConfiguration 情報: Database Controlは正常に起動されました 2014/10/14 18:59:51 oracle.sysman.emcp.EMDBPostConfig performConfiguration 情報: >>>>>>>>>>> Database ControlのURLはhttp://oracle-test-db:1158/emです <<<<<<<<<<< Database Controlの保護中にエラーが発生しました。Database Controlが非セキュア・モードで起動されています。Database Controlを保護するには、次のコマンドを実行してください。 1) 環境変数ORACLE_UNQNAMEを一意のデータベース名に設定します 2) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl stop dbconsole 3) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl config emkey -repos -sysman_pwd < SYSMANユーザーのパスワード > 4) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl secure dbconsole -sysman_pwd < SYSMANユーザーのパスワード > 5) /opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl start dbconsole EMキーを保護するには、/opt/app/oracle/product/11.2.0.4/dbhome_1/bin/emctl config emkey -remove_from_repos -sysman_pwd < SYSMANユーザーのパスワード >を実行します
- OEMの起動はできたがレポジトリが壊れていて接続できなかった。
emca -deconfig dbcontrol db -repos drop
emca -config dbcontrol db -repos create
で解決
Oracle shrinkする上での注意点
Oracleを使用していると、断片化がつらい。
頻繁に更新しているインデックスの断片化が特につらい。
そして表領域を圧迫していく。。
そういう時にEnterpriseEditionであればindex rebuild online
なんてできるけど、
StandardEditionだとできないのでshrink
で対応。
以下のように記述する。
ALTER INDEX indexname SHRINK SPACE;
このshrinkはSEでもオンラインで可能なので、いいんですが注意が必要。
1. ディスク領域
アーカイブログが大量に出力されるのでディスク領域に注意が必要。
単純なディスクサイズの問題もあるし、もし高速リカバリエリアにアーカイブログを保存している場合は使用率の確認が必要。
高速リカバリエリアのサイズを確認しながら、またはdf
コマンドで確認しながらshrinkする。
- 確認SQL
>SELECT nvl(SUM(PERCENT_SPACE_USED),0) FROM v$flash_recovery_area_usage; NVL(SUM(PERCENT_SPACE_USED),0) ------------------------------ 32.86
2. UNDO領域の使用率
shrink中はUNDO領域の使用も大幅に増える。
UNDO領域を食い潰すと更新できずにセッションが詰まる、自動拡張にしていても拡張のタイミングで更新が待たされセッションが詰まる。
よって、UNDO領域の使用率がいっぱいにならないように確認しながら、UNDO領域のパージを待ったりして進める必要あり。
- 確認SQL
select to_char(sysdate,'YYYY/MM/DD HH24:MI:SS') "TIME", round("USED_SIZE(MB)", 3) "USED(MB)", round("TBS_SIZE(MB)", 3) "TBS(MB)", round("USED_SIZE(MB)"/"TBS_SIZE(MB)" * 100, 3) "USAGE(%)" from (select sum(BYTES)/1024/1024 "USED_SIZE(MB)" from DBA_UNDO_EXTENTS where STATUS in ('ACTIVE', 'UNEXPIRED') and TABLESPACE_NAME = 'UNDOTBS1') , (select sum(BYTES)/1024/1024 "TBS_SIZE(MB)" from DBA_DATA_FILES where TABLESPACE_NAME = 'UNDOTBS1') ;
SQLの参考
第28回 UNDO表領域の管理~保存期間の自動チューニング~
3. 解放時のロック
SHRINK SPACE
を実施してると断片化を解消している処理の間は行ロックなので、ほぼオンライン。
しかし、その空いたエクステントを解放するときはテーブルロックをとるので解放する領域が大きいとセッションが詰まってこれまた大変なことに。。。
SHRINK SPACE COMPACT
にすることで、エクステントを解放はせずに断片化だけ解消するのでセグメントのサイズは変わらないが、
空いた領域を再利用してくれるので増加は抑えられる。
または、SHRINK SPACE COMPACT
をしておいて、負荷の少ない時間帯に解放してあげるのが良い。
以上のことを踏まえて、うちではこの辺を自動化して運用してます。