1

我正在 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 本身在提交,而只是TRUNCATESP 中的语句?

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

4

1 回答 1

2

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

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

导致隐式提交的语句


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

TRUNCATE TABLE tablename

或者

ALTER TABLE tablename AUTO_INCREMENT = 1

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

于 2015-07-20T20:46:53.630 回答