MySQL存储过程在同一连接上的第二次调用失败,"SELECT命令被拒绝给用户'用户'@'localhost'用于表'view_name'

jhe*_*cks 5 mysql stored-procedures mysql-error-1142

我有一个名为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();
Run Code Online (Sandbox Code Playgroud)

在第一次调用时,它会执行它应该执行的操作并正常返回.在第二个电话中,我得到:

Error Code: 1142
SELECT command denied to user 'test'@'localhost' for table 'one_pg_someone_sales_observation_daily_summary_view'
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

因此定义了存储过程:

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
Run Code Online (Sandbox Code Playgroud)

我在我的本地开发盒上使用版本5.1.56-log.
更新1 我还在Amazon RDS服务器版本5.1.57-log上重现了该错误.

更新2 如果我定义存储过程SQL SECURITY INVOKER并以root身份执行它,它可以正常工作.这不是一个可接受的解决方法,但它可能是某种线索.(例如,它不是表锁定问题.

更新3 涉及的表是InnoDB表.我不知道这是否是一个线索,但是当我在开始时加入一开始事务和结束时提交,花了更长的时间才能完成,但随后上了第二次调用同样的错误.

更新4 我简化了存储过程并仍然重现了问题.它曾经有一个insert语句后跟一个update语句.事实证明,update语句足以重现错误,因此我从上面的存储过程中删除了insert语句.

Hun*_*ter 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
Run Code Online (Sandbox Code Playgroud)