MySQL事务嵌套

2 篇文章 0 订阅

前言

MySQL 在开始某个事务的时候,会隐式提交上一个事务。所以 MySQL 本身是不支持事务嵌套的。

MySQL 也给我们提供了一个 SAVEPOINT 来做出类似事务嵌套的动作,我们将运用 SAVEPOINT 来帮助我们实现事务嵌套。

MySQL示例

准备一张表,用于测试。

CREATE TABLE `demo_transaction` (
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

部分回滚

-- 格式化
TRUNCATE demo_transaction;

-- 开启事务
BEGIN;

-- 插入一条数据
INSERT INTO `demo_transaction`(id) VALUES(1);

-- 开启 SAVEPOINT
SAVEPOINT t1;
INSERT INTO `demo_transaction`(id) VALUES(2);
-- 回滚 SAVEPOINT
ROLLBACK TO SAVEPOINT t1;

-- 提交事务
COMMIT;

这时候,查询一下表 demo_transaction,会看到表里只有一条数据。

因为 2 的那条数据已经被回滚了。

全部提交

-- 格式化
TRUNCATE demo_transaction;

-- 开启事务
BEGIN;

-- 插入一条数据
INSERT INTO `demo_transaction`(id) VALUES(1);

-- 开启 SAVEPOINT
SAVEPOINT t1;
INSERT INTO `demo_transaction`(id) VALUES(2);
-- 释放 SAVEPOINT
RELEASE SAVEPOINT t1;

-- 提交事务
COMMIT;

这时候,查询一下表 demo_transaction,会看到表里有两条数据。

全部回滚

-- 格式化
TRUNCATE demo_transaction;

-- 开启事务
BEGIN;

-- 插入一条数据
INSERT INTO `demo_transaction`(id) VALUES(1);

-- 开启 SAVEPOINT
SAVEPOINT t1;
INSERT INTO `demo_transaction`(id) VALUES(2);
-- 释放 SAVEPOINT
RELEASE SAVEPOINT t1;

-- 提交事务
ROLLBACK;

这时候,查询一下表 demo_transaction,会看到表里没有数据。

PHP实现

<?php
/**
 * Transactions
 */
trait Transactions
{
    /**
     * transaction nums
     *
     * @var integer
     */
    protected $transactionNums = 0;

    /**
     * begin transaction
     */
    public function beginTrans()
    {
        ++$this->transactionNums;
        if ($this->transactionNums == 1) {
            $this->getDB()->beginTransaction();
        } else {
            $this->query("ROLLBACK TO SAVEPOINT trans{$this->transactionNums}");
        }
    }

    /**
     * rollback transaction
     */
    public function rollback()
    {
        if ($this->transactionNums > 1) {
            $this->query("SAVEPOINT trans{$this->transactionNums}");
        } else {
            $this->getDB()->rollback();
        }
        --$this->transactionNums;
    }

    /**
     * commit transaction
     */
    public function commit()
    {
        while ($this->transactionNums > 1) {
            $this->query("RELEASE SAVEPOINT trans{$this->transactionNums}");
            --$this->transactionNums;
        }
        if ($this->transactionNums) {
            $this->getDB()->commit();
        }
        $this->transactionNums = 0;
    }
}

最后

梳理一下知识,免于踩坑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值