计划事件未正确执行

Scheduled Event not Executing Properly

提问人:Code Magician 提问时间:11/7/2023 最后编辑:user1191247Code Magician 更新时间:11/8/2023 访问量:57

问:

我有一个计划每晚运行的 mysql 事件,定义如下:

create definer = myuser@`%` event nightly on schedule
    every '1' DAY
        starts '2023-10-21 00:00:00'
    enable
    do
    call mydb.nightly_script;

尽管当我查看将由 proc 修改的表时,更新没有发生。如果我从事件中复制该行并执行它,我会看到过程正确执行,但是该事件没有任何反应。call mydb.nightly_script;

我已经完成了基本的故障排除步骤。我已验证事件调度程序是ON

SELECT @@event_scheduler

返回

event_scheduler

而且,当我查看 information_schema 中的 EVENTS 表时,它显示该事件每晚都在运行。

SELECT *
FROM information_schema.EVENTS
WHERE EVENT_NAME = 'nightly';
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME 定义者 TIME_ZONE EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD SQL_MODE 开始 结束 地位 ON_COMPLETION 创建 LAST_ALTERED LAST_EXECUTED EVENT_COMMENT 鼻祖 CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION
def mydb的 夜间 myuser@% 系统 SQL算法 致电mydb.nightly_script 经常性 1 STRICT_TRANS_TABLES 2021-10-21 18:08:00 启用 不保存 2023-10-05 18:07:45 2023-11-05 00:00:45 2023-11-06 00:00:02 2866802262 UTF8MB4的 utf8mb4_general_ci latin1_swedish_ci

尽管一切都表明计划程序正在运行并且事件正在触发,但存储过程要么没有运行,要么以某种方式失败,我不确定如何进一步调查(它是 Azure DBaaS,我不确定如何找到相关日志,如果它们存在的话)。

我尝试了在事件正文中对命令进行一些变体,例如验证过程名称的大小写,使用点表示法完全限定过程,包括或排除过程末尾的parens(它不采用任何参数)等。call

过程和事件的定义者都是我的用户,例如

CREATE
    definer = myuser@`%` procedure nightly()
BEGIN
...

我的用户具有以下 GRANTS:

SHOW GRANTS FOR myuser
myuser@% 的赠款
授予选择、插入、更新、删除、创建、删除、重新加载、处理、引用、索引、更改、显示数据库、创建临时表、锁定表、执行、复制从属、复制客户端、创建视图、显示视图、创建例程、更改例程、创建用户、事件、触发器到带有授权选项的 'MYUSER'@'%'

存储过程本身的主体如下所示:

CREATE
    definer = myuser@`%` procedure AutoTagAll()
BEGIN

  /*Clean up any tables that shouldn't be there*/
    drop table if exists jobuserlist;
    drop table if exists pl;
    drop table if exists listIds;
    drop table if exists OldList;
    
    /*Create staging tables */
    
    CREATE TEMPORARY TABLE OldList(
    listId CHAR(36),
    contactId CHAR(36),
    PRIMARY KEY(contactId, listID))
    ;
    CREATE TEMPORARY TABLE jobUserList
    (
        user_id CHAR(36) PRIMARY KEY,
        company_id CHAR(36)
    );
    CREATE INDEX IXN__jobUserList__company_id on jobUserList (company_id);

    CREATE TEMPORARY TABLE pl
    (
        ListId CHAR(36),
        contactId CHAR(36),
        primary key (listId, contactId)
    );

    CREATE TEMPORARY TABLE listIds(
         listID CHAR(36) PRIMARY KEY,
         listName VARCHAR(200)
     );
     
    insert into jobUserList ( user_id, company_id)
    ...


    /*clean up*/
    drop table if exists jobuserlist;
    drop table if exists pl;
    drop table if exists listIds;
    drop table if exists OldList;

END;

鉴于该事件无法正常运行,我目前在另一台正在连接并进行调用的机器上运行一个 bash 脚本:

...
#Prepare sql query
SQL_Query='call mydb.nightly'

#mysql command to connect to database

mysql -h$MASTER_DB_HOST -u$MASTER_DB_USER -p$MASTER_DB_PASSWD --ssl_mode=REQUIRED -D$MASTER_DB_NAME <<EOF
$SQL_Query
EOF
echo "script complete."

但是,我对这种解决方法的安全性和可靠性不满意,并且更愿意将此工作集成到 RDBMS 调度程序中。

在这一点上,我不确定如何将事件用于我想要的目的。我在活动中遗漏了什么吗?这是错误的方法吗?存储过程本身是否有冗长的内容(在 mydb 中创建临时表、执行插入、更新和删除)?

提前感谢 SO 社区!

存储过程 azure-mysql-database

评论

0赞 Rick James 11/9/2023
$MASTER_DB_USER == myuser 吗?
0赞 Rick James 11/9/2023
你来自“localhost”吗?
0赞 Code Magician 11/19/2023
@RickJames 是的,该 bash 脚本使用与作业相同的用户。它正在从远程主机连接。

答:

0赞 user1191247 11/7/2023 #1

我不确定这是否适用于您的 Azure DB,但您可以尝试查询performance_schema:

SELECT * FROM performance_schema.error_log WHERE `DATA` LIKE '%scheduler%';

如果失败,您可以添加一个简单的日志表,并在您的进程中添加一些日志记录语句:

CREATE TABLE nightly_log (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    message VARCHAR(255) NOT NULL,
    ts DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
);

CREATE
    definer = myuser@`%` procedure AutoTagAll()
BEGIN

    DECLARE _RowCount INT;

    INSERT INTO nightly_log (message) VALUES ('Starting AutoTagAll');

  /*Clean up any tables that shouldn't be there*/
    drop table if exists jobuserlist;
    drop table if exists pl;
    drop table if exists listIds;
    drop table if exists OldList;

    INSERT INTO nightly_log (message) VALUES ('Populating jobUserList...');

    insert into jobUserList ( user_id, company_id)
    select ...

    SET _RowCount = ROW_COUNT();
    INSERT INTO nightly_log (message) VALUES (CONCAT(_RowCount, ' rows inserted into jobUserList'));

    ...
0赞 Pratik Lad 11/8/2023 #2

我在活动中遗漏了什么吗?这是错误的方法吗?

我使用示例存储过程检查了您的方案,它工作正常。您面临问题有两种可能的情况。

  • 检查您在排序过程中使用的所有名称作为表名或您在 Event 中调用的存储过程名称。

在这里,我尝试了以下代码,每分钟都有示例存储过程:

--created sample Stored procedure to insert the rows
DELIMITER //
CREATE PROCEDURE Insertstudent()
BEGIN
    --your code
    insert into student (Id, Name) values (1,'Amy');
END //
    
DELIMITER ;

--created event to insert row on every minute by calling above stored procedure
create event minutelycity
on schedule every '1' minute
   starts '2023-07-11 00:00:00'
enable
do
call mydb.Insertstudent();

您可以看到上面的过程名称在事件中创建和使用它时是相同的。

要验证是否为 On - 执行以下命令:event_scheduler

SHOW PROCESSLIST;

它将输出一个表/条目,您必须使用 UserCommand 查找条目:event_schedulerDaemon

enter image description here

每分钟为我插入行:

enter image description here enter image description here

存储过程本身是否有冗长的内容(在 mydb 中创建临时表、执行插入、更新和删除)?

正如您所说,当您在事件外部调用它时,它工作正常,因此请检查您在事件中使用的 SP 的名称。