【问题标题】:Lumen/Laravel 5.1 - calling stored procedure appears to commit transactionLumen/Laravel 5.1 - 调用存储过程似乎提交事务
【发布时间】:2015-10-10 01:36:20
【问题描述】:

我正在 Lumen 5.1.3 中构建集成测试。我的大多数测试都可以很好地回滚他们的交易。下面是一个成功回滚的总结(我正在简化代码——实际上事务管理是通过我附加到 PHPUnit 的 @before 注释的特征来完成的):

DB::beginTransaction();
DB::table('user')->insert(
            [
                'guid' => $guid,
                'username' => $username,
                'email' => $email,
                'status' => USER_STATUS_ACTIVE,
                'type' => USER_TYPE_REGULAR,
                'created_on' => $currentDateTime
            ]
        );
DB::rollBack();

一切都很好。测试后用户表为空。

现在 - 这就是我感到困惑的地方。如果我在组合中添加一个 SP,事情就不会回滚:

DB::beginTransaction();
DB::table('user')->insert(
            [
                'guid' => $guid,
                'username' => $username,
                'email' => $email,
                'status' => USER_STATUS_ACTIVE,
                'type' => USER_TYPE_REGULAR,
                'created_on' => $currentDateTime
            ]
        );

DB::statement('CALL s_generate_leaderboards(?)', [$oneWeekAgo]);
DB::rollBack();

现在确实提交了新的用户记录。一旦我执行了存储过程,DB::rollBack(); 就没有效果了。

没有错误 - 一切都成功。我什至确保正在到达DB::rollBack(); 命令。

那么 - 如果且仅当我调用了一个 SP,为什么我的事务会被提交?太令人沮丧了.. :(

编辑 1:

你的怀疑是正确的。这是 SP(它很大,所以我已经折叠了 90%):

CREATE PROCEDURE s_generate_leaderboards (IN week_ago_date DATETIME)
BEGIN

-- Empty and regenerate the all-time leaderboard:

TRUNCATE TABLE all_time_leaderboard;

INSERT INTO all_time_leaderboard (...)
...;

-- Empty and regenerate last week's leaderboard:

TRUNCATE TABLE last_week_leaderboard;

INSERT INTO last_week_leaderboard (...)
...;

END

所以也许不是 SP 本身在提交,而只是 SP 中的 TRUNCATE 语句?

TRUNCATE 正在使用,因为排行榜表中有一个 position 列自动递增,需要重置。 DELETE FROM table 不会重置自动增量..

【问题讨论】:

    标签: mysql laravel laravel-5 lumen illuminate-container


    【解决方案1】:

    某些 MySQL 语句会导致隐式提交,从而结束当前会话中活动的任何事务。因此,您的问题可能是由作为存储过程一部分的语句引起的。

    根据程序的名称,我猜您可能正在使用TRUNCATE TABLE 来清空需要刷新信息的表,但我可能错了:)。在任何情况下,您都可以查看我在下面链接的官方 MySQL 文档,看看是否确实如此(因为可能导致这种行为的语句列表有点长):

    Statements That Cause an Implicit Commit


    由于您的列具有自动增量功能并且需要重置它们,因此您可能不走运。因为(据我所知)唯一的两种重置方法是使用:

    TRUNCATE TABLE tablename
    

    ALTER TABLE tablename AUTO_INCREMENT = 1
    

    TRUNCATE TABLEALTER TABLE 都是触发隐式提交的语句。

    【讨论】:

    • 是的,我相信。您可以尝试用DELETE FROM all_time_leaderboard 替换TRUNCATE TABLE all_time_leaderboard 语句(当然last_week_leaderboard 也是如此)。这将清除数据表(尽管它确实有不将主键自动增量值重置为 1 的缺点)。但要测试这是否确实是它必须做的问题。
    • 我已经用解释更新了我的答案,但不幸的是不是一个解决方案。如果您可以发布存储过程的全部内容,也许我可以提供另一种解决方案来以另一种方式生成位置值,尽管我不能保证任何事情:)。
    • 谢谢,我要对我的 SP 进行调整以删除 TRUNCATE,看看你的理论是否正确。在那之后,我(也许在你的帮助下?:))会担心如何重做 SP。无论哪种方式,如果确实是TRUNCATE,我会给你答案,因为我会确切地知道问题所在!
    • 从我的 SP 中删除 TRUNCATE 后,事务确实开始工作了。所以 - 看起来问题一般不在于 SP,这至少是一些好消息。我们系统中有十几个 SP,这是唯一一个执行TRUNCATE 的 SP。这是一个特别的。我要么调整 SP 逻辑,要么在集成测试夹具中适应它的行为。不管怎样,我已经给你答案了;我现在知道问题出在哪里了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    相关资源
    最近更新 更多