mysql 事务嵌套_MySQL 事务嵌套

namespace Illuminate\Database\Concerns;useClosure;use Exception;useThrowable;

trait ManagesTransactions

{/**

* Execute a Closure within a transaction.

*

* @param \Closure $callback

* @param int $attempts

* @return mixed

*

* @throws \Exception|\Throwable*/

public function transaction(Closure $callback, $attempts = 1)

{for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {$this->beginTransaction();//We'll simply execute the given callback within a try / catch block and if we

// catch any exception we can rollback this transaction so that none of this

// gets actually persisted to a database or stored in a permanent fashion.

try{return tap($callback($this), function ($result) {$this->commit();

});

}//If we catch an exception we'll rollback this transaction and try again if we

// are not out of attempts. If we are out of attempts we will just throw the

// exception back out and let the developer handle an uncaught exceptions.

catch (Exception $e) {$this->handleTransactionException($e, $currentAttempt, $attempts);

}catch (Throwable $e) {$this->rollBack();throw $e;

}

}

}/**

* Handle an exception encountered when running a transacted statement.

*

* @param \Exception $e

* @param int $currentAttempt

* @param int $maxAttempts

* @return void

*

* @throws \Exception*/

protected function handleTransactionException($e, $currentAttempt, $maxAttempts)

{//On a deadlock, MySQL rolls back the entire transaction so we can't just

// retry the query. We have to throw this exception all the way out and

// let the developer handle it in another way. We will decrement too.

if ($this->causedByDeadlock($e) &&

$this->transactions > 1) {--$this->transactions;throw $e;

}//If there was an exception we will rollback this transaction and then we

// can check if we have exceeded the maximum attempt count for this and

// if we haven't we will return and try this query again in our loop.

$this->rollBack();if ($this->causedByDeadlock($e) &&

$currentAttempt < $maxAttempts) {return;

}throw $e;

}/**

* Start a new database transaction.

*

* @return void

* @throws \Exception*/

public functionbeginTransaction()

{$this->createTransaction();++$this->transactions;$this->fireConnectionEvent('beganTransaction');

}/**

* Create a transaction within the database.

*

* @return void*/

protected functioncreateTransaction()

{if ($this->transactions == 0) {try{$this->getPdo()->beginTransaction();

}catch (Exception $e) {$this->handleBeginTransactionException($e);

}

}elseif ($this->transactions >= 1 && $this->queryGrammar->supportsSavepoints()) {$this->createSavepoint();

}

}/**

* Create a save point within the database.

*

* @return void*/

protected functioncreateSavepoint()

{$this->getPdo()->exec($this->queryGrammar->compileSavepoint('trans'.($this->transactions + 1))

);

}/**

* Handle an exception from a transaction beginning.

*

* @param \Exception $e

* @return void

*

* @throws \Exception*/

protected function handleBeginTransactionException($e)

{if ($this->causedByLostConnection($e)) {$this->reconnect();$this->pdo->beginTransaction();

}else{throw $e;

}

}/**

* Commit the active database transaction.

*

* @return void*/

public functioncommit()

{if ($this->transactions == 1) {$this->getPdo()->commit();

}$this->transactions = max(0, $this->transactions - 1);$this->fireConnectionEvent('committed');

}/**

* Rollback the active database transaction.

*

* @param int|null $toLevel

* @return void*/

public function rollBack($toLevel = null)

{//We allow developers to rollback to a certain transaction level. We will verify

// that this given transaction level is valid before attempting to rollback to

// that level. If it's not we will just return out and not attempt anything.

$toLevel = is_null($toLevel)? $this->transactions - 1

: $toLevel;if ($toLevel < 0 || $toLevel >= $this->transactions) {return;

}//Next, we will actually perform this rollback within this database and fire the

// rollback event. We will also set the current transaction level to the given

// level that was passed into this method so it will be right from here out.

$this->performRollBack($toLevel);$this->transactions = $toLevel;$this->fireConnectionEvent('rollingBack');

}/**

* Perform a rollback within the database.

*

* @param int $toLevel

* @return void*/

protected function performRollBack($toLevel)

{if ($toLevel == 0) {$this->getPdo()->rollBack();

}elseif ($this->queryGrammar->supportsSavepoints()) {$this->getPdo()->exec($this->queryGrammar->compileSavepointRollBack('trans'.($toLevel + 1))

);

}

}/**

* Get the number of active transactions.

*

* @return int*/

public functiontransactionLevel()

{return $this->transactions;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值