У меня есть таблица с именем sales_observation_daily_summary, которая представляет собой материализованное представление sales_observation_daily_summary_view.Я определил хранимую процедуру с именем sync_daily_summary_view_with_table, которая обновит материализованное представление.Функционально все работает именно так, как я ожидаю.Тем не менее, у меня есть странная ошибка при вызове хранимой процедуры дважды на том же соединении (вероятный сценарий при использовании пула соединений).Первоначально это встречалось в моих тестах интеграции Java, но я могу легко воспроизвести его на MySQL Workbench, поэтому он не должен иметь ничего общего с JDBC или Spring или чем-то посередине, как это.
call sync_daily_summary_view_with_table();
call sync_daily_summary_view_with_table();
При первом вызове он делает то, что должен, и возвращает нормально.При втором вызове я получаю:
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
Я использую log-версию 5.1.56 в своем локальном окне разработки.
UPDATE 1 Я также воспроизвел ошибку на сервере 5.1.57-журнала Amazon RDS.
ОБНОВЛЕНИЕ 2 Если я определяю хранимую процедуру как SQL SECURITY INVOKER
и выполняю ее как root, она работает нормально.Это не приемлемый обходной путь, но это может быть какая-то подсказка.(Например, это не проблема блокировки таблиц.
UPDATE 3 Используемые таблицы являются таблицами InnoDB. Я не уверен, что это подсказка, но когда я добавил Start Transaction вначало и фиксация в конце, это заняло гораздо больше времени, но затем я получил ту же ошибку при втором вызове.
ОБНОВЛЕНИЕ 4 Я упростил хранимую процедуру и все еще воспроизводилПроблема: раньше использовался оператор вставки, за которым следовал оператор обновления. Оказалось, что оператора обновления достаточно, чтобы воспроизвести ошибку, поэтому я удалил оператор вставки из хранимой процедуры выше.