1. MySQL默认自动提交(autocommit=1),如果要开启事务,先关闭自动提交(autocommit=0);
  2. InnoDB支持事务,MyISAM不支持;
  3. MySQL不支持事务嵌套;已经开启事务后,再开启事务(start transaction),会隐式的提交(commit)上一个事务。

MySQL中可以通过部分事务(savepoint)来实现嵌套

TRUNCATE nested_transaction;
BEGIN;
INSERT INTO `nested_transaction`(id) VALUES(1);
SAVEPOINT t1;
INSERT INTO `nested_transaction`(id) VALUES(2);
ROLLBACK TO SAVEPOINT t1;
COMMIT;

id
--------
1

PHP中Laravel中事务嵌套(ManagesTransactions.php)

<?php

namespace Illuminate\Database\Concerns;

use Closure;
use Exception;
use Throwable; 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 function beginTransaction()
{
$this->createTransaction(); ++$this->transactions; $this->fireConnectionEvent('beganTransaction');
} /**
* Create a transaction within the database.
*
* @return void
*/
protected function createTransaction()
{
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 function createSavepoint()
{
$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 function commit()
{
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 function transactionLevel()
{
return $this->transactions;
}
}

也可以只开启一个事物,判断如果是嵌套事务,则不做操作直接返回。

MySQL 事务嵌套的更多相关文章

  1. MySql中的事务嵌套

    1.Mysql中的事务必须是InnoDB.Berkeley DB引擎,myisam不支持. 2.Mysql是不支持嵌套事务的,开启了一个事务的情况下,再开启一个事务,会隐式的提交上一个事务. 3.My ...

  2. Mysql事务及行级锁的理解

    在最近的开发中,碰到一个需求签到,每个用户每天只能签到一次,那么怎么去判断某个用户当天是否签到呢?因为当属表设计的时候,每个用户签到一次,即向表中插入一条记录,根据记录的数量和时间来判断用户当天是否签 ...

  3. 第五章 MySQL事务,视图,索引,备份和恢复

    第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行 ...

  4. Mysql事务及行级锁

    事务隔离级别 数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果. Read Uncommitted (读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离 ...

  5. 10.mysql事务管理及python操作

    在用户操作MySQL过程中,对于一般简单的业务逻辑或中小型程序而言,无需考虑应用MySQL事务.但在比较复杂的情况下,往往用户在执行某些数据操作过程中,需要通过一组SQL语句执行多项并行业务逻辑或程序 ...

  6. mysql事务的开启

    mysql事务的开启 对于一个MYSQL数据库(InnoDB),事务的开启与提交模式无非下面这两种情况: 1>若参数autocommit=0,事务则在用户本次对数据进行操作时自动开启,在用户执行 ...

  7. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  8. MySQL实现嵌套集合模型

    MySQL实现嵌套集合模型 译文主要是介绍如何用MySQL来存储嵌套集合数据.在其中会增加一些自己的理解,也会删除掉一些自认为无用的废话. 这篇文章主要讲的是嵌套集合模型,所以邻接表不是本文的重点,简 ...

  9. MySQL 事务

    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成 ...

随机推荐

  1. UVA 1347(POJ 2677) Tour(双色欧几里德旅行商问题)

    Description John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane a ...

  2. 编码(encode)问题

    1. UTF-8 与 GBK UTF-8: 允许含 BOM,但通常不含 BOM 用以解决国际上字符的一种多字节编码, 英文:8 bits(1 byte) 中文:24 bits(3 bytes) UTF ...

  3. Git 内部原理--初探 .git

    说到Git大家应该都非常熟悉,几乎每天都会用到它.在日常使用过程中,我们貌似并不需要关注其内部的原理,只需要记住那几个常用的命令,就可以说自己是会Git的人了.可是,事实真的是这样子的吗?今天我们就来 ...

  4. 用callgraph生成的函数调用关系图

    Wu Zhangjin 创作于 2015/04/05 评论打赏 By Falcon of TinyLab.org 2015/04/03 1 故事缘由 源码分析是程序员离不开的话题.无论是研究开源项目, ...

  5. WPF特效-粒子动画

    原文:WPF特效-粒子动画 WPF实现泡泡龙小游戏效果.     /// -Ball to Ball Collision - Detection and Handling    /// http:// ...

  6. Token的设计(2)

    词法分析 Token的几个种类 前端的第一步就是词法分析, 这个过程通俗来讲就是将源代码转化为一串Tokens. 所以首先应该想到的是, 到底该有哪几种类型的Token ? 关于这个问题我已经想过了, ...

  7. Expression Blend学习二UI布局

    什么是布局? · Panels控件(其实就是容器控件) · 对内部的子控件提供了自动布局功能 · 可以在容器控件内继续添加容器控件(一个复杂的界面往往是多种容器控件嵌套而组成的) · 一些界面器控件也 ...

  8. 【shell】分享高通平台刷版本简单的一个shell脚本

    #!/bin/shadb wait-for-deviceadb reboot bootloaderecho "start download"wait 5sudo fastboot ...

  9. Win10商店芒果TV UWP版更新,新增后台视频下载

    湖南卫视旗下唯一官方视频平台<芒果TV>近日向Win10商店提交了芒果TV UWP V3.0.0版,这次为广大Win10平台用户带来了期待已久的重大功能和更新,可谓是良心厂商,值得鼓励和支 ...

  10. HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容。

    解决方法: 找到目录浏览,打开,点击右边的启用就OK了.