Lumen/Laravel 5.1 - 调用存储过程似乎提交事务
Lumen/Laravel 5.1 - calling stored procedure appears to commit transaction
我正在 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();
一切都很好。测试后用户table为空
现在 - 这是我感到困惑的地方。如果我在组合中添加 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
,因为排行榜 table 中有一个 position
列会自动递增,需要重新设置。 DELETE FROM table
不重置自动递增..
一些 MySQL 语句会导致隐式提交,结束当前会话中任何活动的事务。因此,您的问题可能是由存储过程中的语句引起的。
根据过程的名称,我猜您可能正在使用 TRUNCATE TABLE
来清空 table,您需要在其中刷新信息,但我可能是错的:)。在任何情况下,您都可以查看我在下面链接的官方 MySQL 文档,看看是否确实如此(因为可能导致此行为的语句列表有点长):
由于您有自动递增的列并且需要重置它们,您可能不走运。因为只有两种方法(据我所知)可以使用:
TRUNCATE TABLE tablename
或
ALTER TABLE tablename AUTO_INCREMENT = 1
但是TRUNCATE TABLE
和ALTER TABLE
都是触发隐式提交的语句。
我正在 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();
一切都很好。测试后用户table为空
现在 - 这是我感到困惑的地方。如果我在组合中添加 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
,因为排行榜 table 中有一个 position
列会自动递增,需要重新设置。 DELETE FROM table
不重置自动递增..
一些 MySQL 语句会导致隐式提交,结束当前会话中任何活动的事务。因此,您的问题可能是由存储过程中的语句引起的。
根据过程的名称,我猜您可能正在使用 TRUNCATE TABLE
来清空 table,您需要在其中刷新信息,但我可能是错的:)。在任何情况下,您都可以查看我在下面链接的官方 MySQL 文档,看看是否确实如此(因为可能导致此行为的语句列表有点长):
由于您有自动递增的列并且需要重置它们,您可能不走运。因为只有两种方法(据我所知)可以使用:
TRUNCATE TABLE tablename
或
ALTER TABLE tablename AUTO_INCREMENT = 1
但是TRUNCATE TABLE
和ALTER TABLE
都是触发隐式提交的语句。