已经2天了,我正在尝试解决问题,但仍然失败。谢谢任何可以在此问题上提供帮助的人。
错误
我不断收到此消息:
Doctrine\DBAL\Driver\PDOException : SQLSTATE[42000]: Syntax error or access violation: 1305 SAVEPOINT trans3 does not exist
操作期间有一个复杂的过程,我需要检查几个表。在经历多个功能时,该过程将生成嵌套事务。
这不是我第一次使用事务,甚至不是嵌套事务,到目前为止一切都正常。只有此函数会触发错误。
即使我从函数中删除了the DB::beginTransaction()
及其朋友,我仍然有错误。除了“ trans3”变为“ trans2”。
为了触发错误,我将功能代码简化为最简单的
public function doStuff(Stuff $stuff, User $user)
{
$thing = Thing::where('user_id', $user->id)
->where('other_id', $stuff->id)
->get()
->first();
$thing->delete();
return false;
}
我已经尝试过的东西
$thing->fill(['property' => false]); $thing->save();
时设置保存操作,同样的错误。如果该属性与数据库中的属性相同,则不会发生错误(例如$thing->fill(['property' => true]); $thing->save();
不会触发错误,因为不会触发更新)。DB::raw('raw SQL')
,没什么区别。DB::delete('RAW SQL');
,没什么区别。 技术环境
Laravel 5.5
适用于使用readline 5.2的debian-linux-gnu(x86_64)的mysql Ver 15.1 Distrib 10.0.36-MariaDB
PHP 7.0.32-0ubuntu0.16.04.1
我目前唯一想到的解决方案是删除所有父代代码中的所有事务。即使我忽略了它所代表的危险,它所需要的时间也超出了范围,因此,我想确保没有其他选择。
有人有什么主意,领导力吗?
谢谢您的宝贵时间。
答案 0 :(得分:1)
就我而言,它在我的本地环境中工作,但在 CI 中失败。 终于,我找到了重点。 本地 MySQL
sql_mode: NO_ZERO_IN_DATE, NO_ZERO_DATE, NO_ENGINE_SUBSTITUTION
CI MySQL
sql_mode: STRICT_TRANS_TABLES, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION
发现创建表的时候没有给出varchar类型的默认值,赋值的时候忘记写了。
因此,就我而言,主要原因是mysql严格模式。
可能对你有帮助。 (顺便说一句,我用的框架不是laravel。)
答案 1 :(得分:0)
这个答案来得太晚了,但是我遇到了同样的问题。
只有当我决定尝试删除事务时,才发现存在潜在错误。插入其中之一导致了违反完整性约束的错误,我测试该错误时报告为SQLSTATE[42000]: Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist
。
解决基本错误后,我恢复了交易,一切正常。
答案 2 :(得分:0)
这不是解决方案,只是一种解决方法,并不能真正令人满意。但是,它仍然帮助我避免了几个问题。
我创建了一个TransactionService
class TransactionService
{
/**
* @return bool
* @throws \Exception
*/
public function beginTransaction() {
if(DB::transactionLevel() === 0) {
DB::beginTransaction();
return true;
}
return false;
}
/**
* @param bool $ongoingTransaction
*/
public function commit($ongoingTransaction) {
if($ongoingTransaction === true) {
DB::commit();
}
}
/**
* @param bool $ongoingTransaction
*/
public function rollBack($ongoingTransaction) {
if($ongoingTransaction === true) {
DB::rollBack();
}
}
}
我仅通过它使用数据库事务:
$sqlOngoingTransaction = Transaction::beginTransaction();
try {
// do stuff
} catch (\Exception $e) {
Transaction::rollBack($sqlOngoingTransaction);
throw($e);
}
Transaction::commit($sqlOngoingTransaction);