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 ステートメントを削除しました。