質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

4回答

5965閲覧

webからvacuumの実行

aokyun

総合スコア13

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2018/07/03 05:10

編集2018/07/03 05:58

管理画面からvacuumが実行できる機能を作成したのですが
エラーが発生し、どうにもうまくいきません。

■パターン1・・・execにてコマンドを実行

// 実行コマンド $cmd = "nohup vacuumdb table_name -z db_name &"; exec($cmd, $output, $res); // エラーメッセージ ignoring input and redirecting stderr to stdout

試みたこと
・vacuumdb table_name -z db_nameに修正して実行
→exec()のreturn_val引数が1で異常終了

■パターン2・・・pg_execでSQLとして実行

// 実行SQL $sql = "VACUUM FREEZE ANALYZE table_name"; pg_exec($sql); // エラーメッセージ VACUUM cannot run inside a transaction block

試みたこと
・begin; vacuum; commit;
→VACUUM cannot run inside a transaction blockでエラー
・end transaction; vacuum;
→VACUUM cannot be executed from a function or multi-command stringでエラー

(備考)
社内の開発環境ではパターン1で正常に動作していますが、パターン2はどれもエラー
本番環境ではパターン1、2ともにどの手法でもエラーとなっています。

上記のロジックは関数化してあり、table_nameは引数で受け取っています。
どのテーブルにバキュームをかけるかはユーザが指定します。

google先生に聞いてみたものの、試せるものは試してみましたがうまくいきません。
コマンドラインやpgadminのような管理ツールからの実行はうまくいきます。

打開策が浮かばなかったため、知恵をお借りできればと思います。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/07/03 05:12

実際のPHPコードをご提示ください。パスワードなどセキュリティに関わる箇所は適当にマスクをかけてください。
m.ts10806

2018/07/03 05:24

いきなりpg_exec()利用されてますが、接続処理はきちんと書いて、接続成功しているんですよね?
aokyun

2018/07/03 05:28

そうですね、コネクションの部分は自社ライブラリを使用していて載せきることができないため割愛しています。DBへの接続に関しては問題ないことは確認できています。
m.ts10806

2018/07/04 02:01

私の回答とコメントでは解決策としては不十分なので、 まとめた上で自身で回答を書かれて自己解決とされた方が良いです。 「ベストアンサー」の回答は後から見たときに一番目に付きます。
guest

回答4

0

これかな?
PostgreSQL で VACUUM コマンドが使えない

VACUUM コマンド(不要領域の回収処理)を実行しようとすると、「ERROR: VACUUM cannot run inside a transaction block」といったエラーとなる。現状(ver 1.5.0)の Fio は、JDBC の Auto Commit モードを false にして動作しており、これがエラーの原因である。
一応設定ファイルで Auto Commit モードを true にもできるなど対応の準備は進めているのだが、現段階ではサポートできていない。

PHPのドライバーも同じ動作をしていると仮定するなら、意図通りに動作するか分かりませんが、postgresにvcuumeするストアドを作成してテーブル名はパラメータで渡す。

あ、それ以前にAuto Commit モードを確認すれば済む話かもしれませんね。

投稿2018/07/03 05:54

編集2018/07/03 06:29
sazi

総合スコア25138

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokyun

2018/07/03 06:30

autocommitは自分も知らなかったので相談してみますが、なにやら怖そうな機能ですね。。 ストアドは思いつかなかったのでちょっと作成してみます。
sazi

2018/07/03 06:33

auto commitモード=Trueでも、トランザクション制御すれば勝手にCOMMITはされません。
aokyun

2018/07/03 06:36

本番サーバを確認してみたところ、auto commitモードはonになっていました。
guest

0

エラーメッセージからも、パターン2の方はきちんとトランザクション内で利用すれば通りそうに思います。

[更新系SQL実行]をトランザクション外で実行することはできません。

上記はJavaですが、PHPでも概念は同じです。

投稿2018/07/03 05:25

m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokyun

2018/07/03 05:36

この記事も拝見しました。 このやり方は上記で記載している「pgadminのような管理ツールからの実行はうまくいきます」に該当する内容だと認識しています。 トランザクション内で実行されていることが問題というのは別サイトにも情報として載っていましたが 打開策として提示されていた ・vacuum文の前に「END TRANSACTION」を実行 ・commit; vacuum; commit; 上記方法どちらでも解決はしませんでした。
m.ts10806

2018/07/03 05:41

ちょっとコメントずれました。失礼しました。 回答にあるとおり「ランザクション外で実行することはできません」なので、 BEGINしてその間にVACUUMを実行し、成功したらCOMMITしてください。
otn

2018/07/03 05:41

> きちんとトランザクション内で利用すれば 「外」のまちがいですよね。 アダプタではトランザクション外で実行できないと書いてあるので、無理ではないですか?
aokyun

2018/07/03 05:42

BEGIN; VACUUM; COMMIT; この形でのSQLも試してみましたが同じエラーが発生します。 >VACUUM cannot run inside a transaction block
m.ts10806

2018/07/03 05:44 編集

ちょっと勘違いしていました。 「inside a ~~」ですもんね。 失礼しました。 otnさん ご指摘ありがとうございます。 別策考えます。
aokyun

2018/07/03 05:47

もうちょっと詳細な話をすると、execでコマンド実行する分に関しては社内環境では動作しています。 ただ、本番環境だと実行自体はできるのですが、レスポンスがなく統計情報の更新もされません。 今のところ権限等の問題があるのでは、という見解です。 (pg_execでは実現不可能なのかもしれません。。)
sazi

2018/07/03 05:48

>mts10806さん いやいや、エラーはトランザクション中は駄目よってエラーだからなんとかそれ終わらせようと言うことです。 >anokyunさん VACUME専用の別なコネクションを作ってそちらで発行してみてはどうですか。
m.ts10806

2018/07/03 05:48

ちょっと後出しの情報が多いですね・・・ 要件整理して質問更新していただけますか? 各コメントだと他の見ている人の目につきません。
sazi

2018/07/03 05:49

う、コメントがいっぱい付いてた。失礼しました。
m.ts10806

2018/07/03 06:14

超ミニマムコード試してみたのですが、同エラーは確認できませんでした。 ---------------------- $table = $_POST["table"]; try{ $sql = "VACUUM FREEZE ANALYZE ".$table; $res = pg_query($con,$sql); if(!$res){ throw new Exception(); } $msg = "成功"; }catch (Exception $e){ $msg = $e->getMessage(); } ---------------------- saziさんが仰っている別コネクションという策が良さそうです。 それかいっそ、新しくテーブル作ってそちらに全てコピーして元のテーブル削除してテーブル名変更する・・・という手続き的なやり方もありですね。 VACUUMって結構時間かかることありますし。 と思ったらVACUUM FULLの変わりにやるという記事がありました。 http://www.1x1.jp/blog/2007/11/postgresql_no_vacuum_full.html
sazi

2018/07/03 06:20

>mts10806さん その方法は新たなテーブルを同名で作るという方法で、確かに新しいテーブルには不要なタプルは残っていません。ですが物理的な容量を開放するにはVACUME FULLしか無いので、トータルの時間は逆に増える事になります。
m.ts10806

2018/07/03 06:25

なるほど。勉強になります。
aokyun

2018/07/03 06:25

別テーブルで、というのは自分もネットで拝見し考えましたが 日常的にメンテナンスの必要性が発生することから、サーバの容量や負荷等を考慮した結果採用しませんでした。
m.ts10806

2018/07/03 06:25

今回FULLじゃないらしいので、該当しませんね。ちょっと考えすぎました。
aokyun

2018/07/03 07:19

ご協力いただきありがとうございました。 SQLでの解決とはなりませんでしたが、コマンドの調整を行い無事正常に実行することができました。
m.ts10806

2018/07/03 07:22

私の回答とコメントでは解決策としては不十分なので、 まとめた上で自身で回答を書かれて自己解決とされた方が良いです。 「ベストアンサー」の回答は後から見たときに一番目に付きます。
guest

0

自己解決

自己解決しました、ご協力いただきありがとうございました。

(追記)

問題のあったコマンド

nohup vacuumdb -h localhost -U postgres table_name -z db_name &

非常にお恥ずかしい話ではありますが、システムのサーバ構築がWEBとDBとを分離していたことが分かり
localhostをDBのアドレスに変更したところ本番でもうまくいきました。
社内環境でうまくいっていたのはサーバが同居していたためです。

依然、SQLのほうではうまくいっていないため、こちらに関しては他の方にお任せしようと思います。

投稿2018/07/04 02:05

編集2018/07/04 02:24
aokyun

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/07/04 02:08

「解決方法」を記載してください。 これだけではどう解決したか分かりませんので。
sazi

2018/07/04 02:09

自己解決した方法をこの回答に残していただけると、同じ問題で困っている人の助けになりますので、お手数ですが、是非お願いします。
sazi

2018/07/04 02:10

個人的にも知りたい。
sazi

2018/07/04 02:54 編集

成程。 SQLの方は、タイムアウトかもしれませんね。タイムアウト無制限の別セッションで実行してみるとか。 ちょっと気になりますが、コマンドの方は、コマンド発行するだけで、その結果は預かり知らないことになっていないかという点。 実際に処理するのは別プロセスにして、それを起動するという仕組みの方が良いかもしれない。
guest

0

これらのコマンドを実際に実行する部分のPHPコードも載せたほうがいいですね。
VACUUMが終わるのを待つのか、待たずに「実行開始しました」と表示するだけで済むのかによってコマンドも変わります。

nohup: ignoring input and redirecting stderr to stdout

これはエラーではありません。
ちゃんと読めばわかるのですが、「入力を無視し、 stderrをstdoutにリダイレクトします」というメッセージです。
nohup は主にSSHログアウト時にHUPシグナルによる処理停止が起こらないようにするなどの用途で使われるもので、今回は不要だと思います。

投稿2018/07/03 05:19

mather

総合スコア6753

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokyun

2018/07/03 05:31

nohup vacuumdb table_name -z db_name 上記コマンドで試してみたところ、コマンドラインからは正常に実行できました。 ただ、webからの実行はエラーが発生し、戻り値も「1」が返却されました。
mather

2018/07/03 05:41

回答をちゃんと読みましたか?意味がわからない部分があったらどの部分が理解できないのか質問してください。 コマンドラインからは成功するんです、と主張されても、やりたいことはコマンドラインとは違いますよね。 「エラーが発生し」「戻り値も1」の意味がわからないので、PHPのコードを提示してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問