关于TP Db::execute创建表或修改表会自动提交事务的问题

3 篇文章 0 订阅
1 篇文章 0 订阅

ThinkPHP 5.0.24
MySql 5.7.26

遇到的问题:
当前需求需要根据不同类型对表添加新的字段,并且这其中还有对(其他)表的增删改查。我打算通过事务来实现所有的数据库操作,理想情况下是可以在出错的时候进行回滚,包括建表建字段这种情况。

然而实际情况是,建表建字段是无法进行回滚的,能回滚的只有数据。而且即使建字段的时候发生了错误,之前的对数据的操作也会被直接被提交。

举个例子:
存在一个表 user
在这里插入图片描述
假设我需要修改id=1的name,并且添加一个字段 sex。但是当前sex已经存在,添加的话肯定会报错:

// 添加字段
$sql = "ALTER TABLE `user` ADD `sex` tinyint(4) NOT NULL DEFAULT 0 COMMENT '性别'; ";
// 开启事务
Db::startTrans();
try {
	// 修改id=1的name
    Db::name('user')->update(['id'=>1,'name'=>'小明'.rand(1,999)]);
    Db::execute($sql);
    
    // 提交事务
    Db::commit();
    var_dump('success');
}catch (\Exception $e){
	// 回滚事务
    Db::rollback();
    var_dump($e->getMessage());
}

执行后:
在这里插入图片描述
在这里插入图片描述
即使打印了错误,但是数据库中的name还是被修改了。

分析和解决方法
一开始我还以为是TP框架做了限制之类的,然后我通过使用SQL直接执行:

BEGIN;

UPDATE `user` SET `name` = '小明666' WHERE id = 1;

ALTER TABLE `user` ADD `sex` tinyint(4) NOT NULL DEFAULT 0 COMMENT '性别';

COMMIT;

还是一样的结果,所有我猜想这可能就是mysql的机制吧。
解决方法的话,可能就是把DML操作和DDL操作分开来写,DDL操作要独立处理错误,而DML就可以直接catch然后rollback。

扩展:
MySQL的自动提交模式
DQL、DML、DDL、DCL的概念与区别

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值