5

sales_observation_daily_summary_view の実体化されたビューである sales_observation_daily_summary というテーブルがあります。具体化されたビューを更新する sync_daily_summary_view_with_table というストアド プロシージャを定義しました。機能的には、期待どおりに動作します。ただし、同じ接続でストアド プロシージャを 2 回呼び出すと、奇妙なバグが発生します (接続プールを使用する場合に発生する可能性が高いシナリオです)。もともとこれは私の Java 統合テストで発生しましたが、MySQL Workbench で簡単に再現できるので、JDBC や Spring などとは関係ありません。

call sync_daily_summary_view_with_table();
call sync_daily_summary_view_with_table();

最初の呼び出しで、本来の処理を実行し、正常に戻ります。2 番目の呼び出しで、次のようになります。

Error Code: 1142
SELECT command denied to user 'test'@'localhost' for table 'one_pg_someone_sales_observation_daily_summary_view'

one_pg_someone_sales_observation_daily_summary_view は、ストアド プロシージャで参照される sales_observation_daily_summary_view で参照されます。まず第一に、ストアド プロシージャが最初に実行されたときにオブジェクトを生成せず、第二に、そのユーザーがそのビューで選択する十分な権限を持っているため、エラー メッセージは意味がありません。

関連するすべてのビューは非常に複雑なので表示しませんが、sales_observation_daily_summary_view は他のいくつかのビューの結合として定義されています。

CREATE ALGORITHM=UNDEFINED DEFINER=`test`@`localhost` 
SQL SECURITY DEFINER 
VIEW `sales_observation_daily_summary_view` AS
        /* Specific Stage and Observer */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   one_pg_someone_sales_observation_daily_summary_view
        UNION ALL /* All Stages */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   all_stages_someone_sales_observation_daily_summary_view
        UNION ALL /* All Activities */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   all_activities_someone_sales_observation_daily_summary_view
        UNION ALL /* All Observers */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   one_pg_everyone_sales_observation_daily_summary_view
        UNION ALL /* Everyone over All Stages */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   all_stages_everyone_sales_observation_daily_summary_view
        UNION ALL /* Everyone over All Activities */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   all_activities_everyone_sales_observation_daily_summary_view
        UNION ALL /* Benchmark */
        SELECT zone,
               session_date,
               session_year,
               session_month,
               session_week,
               phenomenon_group_id,
               phenomenon_group_name,
               stage_id,
               stage_name,
               observer_id,
               series_name,
               benchmark_id,
               session_count,
               session_value,
               benchmark_value
        FROM   benchmark_sales_observation_daily_summary_view

ストアド プロシージャは次のように定義されます。

DELIMITER $$

CREATE DEFINER=`test`@`localhost` PROCEDURE `sync_daily_summary_view_with_table`()
BEGIN

                /* Update any values that may have changed */
                UPDATE sales_observation_daily_summary tb, 
                       sales_observation_daily_summary_view vw 
                SET    tb.session_count = vw.session_count, 
                       tb.session_value = vw.session_count, 
                       tb.benchmark_value = vw.benchmark_value,
                       tb.series_name = vw.series_name 
                WHERE  vw.zone = tb.zone 
                       AND vw.session_date = tb.session_date 
                       AND Coalesce(vw.phenomenon_group_id, 0) = 
                           Coalesce(tb.phenomenon_group_id, 0) 
                       AND Coalesce(vw.stage_id, 0) = Coalesce(tb.stage_id, 0) 
                       AND Coalesce(vw.observer_id, 0) = Coalesce(tb.observer_id, 0) 
                       AND Coalesce(vw.benchmark_id, 0) = Coalesce(tb.benchmark_id, 0) 
                       AND ( Coalesce(tb.session_count, -1) <> Coalesce(vw.session_count, -1) 
                              OR Coalesce(tb.session_value, -1) <> 
                                 Coalesce(vw.session_value, -1) 
                              OR Coalesce(tb.benchmark_value, -1) <> 
                                 Coalesce(vw.benchmark_value, -1) 
                              OR tb.series_name <> vw.series_name ); 
END

ローカル開発ボックスでバージョン 5.1.56-log を使用しています。
UPDATE 1 また、Amazon RDS サーバーのバージョン 5.1.57-log でエラーを再現しました。

UPDATE 2 ストアド プロシージャを定義しSQL SECURITY INVOKERてルートとして実行すると、正常に動作します。これは受け入れられる回避策ではありませんが、何らかの手がかりになる可能性があります。(例: テーブルのロックの問題ではありません。

UPDATE 3 関連するテーブルは InnoDB テーブルです。それが手がかりかどうかはわかりませんが、最初に Start Transaction を追加し、最後に Commit を追加すると、完了するまでにはるかに時間がかかりましたが、2 回目の呼び出しで同じエラーが発生しました。

更新 4 ストアド プロシージャを簡略化しましたが、問題を再現しました。以前は、insert ステートメントの後に update ステートメントが続きました。エラーを再現するには update ステートメントで十分であることが判明したため、上記のストアド プロシージャから insert ステートメントを削除しました。

4

4 に答える 4

2

自動コミットの価値は何ですか? @@autocommit を選択します。

値が 0 の場合は、2 つの呼び出しの間にコミットを追加してみてください。何らかの方法で開いているトランザクションを持つことができるため、sync_daily_summary_view_with_table(); を呼び出します。専念; sync_daily_summary_view_with_table() を呼び出します。

マテリアライズド テーブルはいずれかのビューの一部ですか?

于 2011-09-07T19:32:41.163 に答える
0

これは、1つのクエリで複数のステートメントを許可する場合に問題になる可能性があるようです

this(http://dev.mysql.com/doc/refman/5.0/en/mysql-set-server-option.html)はオプションかもしれません:

mysql_set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_ON)

接続中またはそれ以上:

mysql_real_connect (
    mysql, 
    host_name, 
    user_name, 
    password,
    db_name, 
    port_num, 
    socket_name, 
    CLIENT_MULTI_STATEMENTS)

より良い説明については、こちらもご覧ください:http: //dev.mysql.com/doc/refman/5.0/en/c-api-multiple-queries.html

于 2011-09-09T10:11:24.570 に答える
0

これはトランザクションの問題である可能性があります。UPDATE ステートメントと INSERT ステートメントの後に COMMIT を追加してみてください。まだ InnoDB を使用していない場合は、試してみることもできます。

次のような関数を試して、同じ結果が得られるかどうかを確認してください。

DELIMITER $$

CREATE DEFINER=`test`@`localhost` PROCEDURE `sync_daily_summary_view_with_table`()
BEGIN

            /* Update any values that may have changed */
            UPDATE sales_observation_daily_summary tb, 
                   sales_observation_daily_summary_view vw 
            SET    tb.session_count = vw.session_count, 
                   tb.session_value = vw.session_count, 
                   tb.benchmark_value = vw.benchmark_value,
                   tb.series_name = vw.series_name 
            WHERE  vw.zone = tb.zone 
                   AND vw.session_date = tb.session_date 
                   AND Coalesce(vw.phenomenon_group_id, 0) = 
                       Coalesce(tb.phenomenon_group_id, 0) 
                   AND Coalesce(vw.stage_id, 0) = Coalesce(tb.stage_id, 0) 
                   AND Coalesce(vw.observer_id, 0) = Coalesce(tb.observer_id, 0) 
                   AND Coalesce(vw.benchmark_id, 0) = Coalesce(tb.benchmark_id, 0) 
                   AND ( Coalesce(tb.session_count, -1) <> Coalesce(vw.session_count, -1) 
                          OR Coalesce(tb.session_value, -1) <> 
                             Coalesce(vw.session_value, -1) 
                          OR Coalesce(tb.benchmark_value, -1) <> 
                             Coalesce(vw.benchmark_value, -1) 
                          OR tb.series_name <> vw.series_name ); 
            COMMIT;
END
于 2011-09-06T22:19:26.600 に答える
0

皆さんがこの問題の解決策を見つけたかどうかはわかりません。私は同じことに遭遇し、それを修正することができました!

プロシージャを介してビューで選択しようとしたときに発生した問題。初めてはうまくいきましたが、2回目以降は、ユーザーへのコマンド拒否メッセージに応答していました。

解決策は、「管理者」ユーザーでビューを作成し、手順と同じにする(「管理者」ユーザーで作成する)ことでした。それらのプロセスを実行しました。

問題は、MySQLが別のユーザーを使用してビューを選択し、定義者またはログに記録されたセッションユーザーを使用せず、2回目にこの「内部」ユーザーがコマンドを拒否されることです。ビューから。

皆さんがこの問題を解決するのを手伝ってくれることを願っています!

于 2014-12-16T20:36:00.093 に答える