webman 事务回滚失效问题记录

server/2024/10/21 13:57:28/

webman 事务回滚失效问题记录

简单介绍下webman

webman是一款基于workerman开发的高性能HTTP服务框架。webman用于替代传统的php-fpm架构,提供超高性能可扩展的HTTP服务。你可以用webman开发网站,也可以开发HTTP接口或者微服务。

除此之外,webman还支持自定义进程,可以做workerman能做的任何事情,例如websocket服务、物联网、游戏、TCP服务、UDP服务、unix socket服务等等。

是否推荐大家使用

首先,小编不会推荐看到的朋友使用,不是因为它不好,而是因为有更多的选择.

事务回滚失效问题排查

一段很普通的代码逻辑:更新订单退款状态字段+新增退款申请记录.然后在一个事务里就行原子操作.

    return Db::transaction(function () use ($order, $explain) {$order->refund_status = OrderEnum::ORDER_REFUND_STATUS_ING;$order->save();$orderRefundModel = new OrderRefund();$orderRefundModel->refund_id = 'R' . date('YmdHis') . random_int(10000, 99999);$orderRefundModel->order_id = $order->order_id;$orderRefundModel->status = OrderEnum::ORDER_REFUND_APPLY_STATUS_ING;$orderRefundModel->refund_price = $order->paid_amount;$orderRefundModel->refund_num = 1;$orderRefundModel->refund_phone = $order->user_mobile;$orderRefundModel->refund_explain = $explain;$orderRefundModel->save();return $orderRefundModel->id;});

这样的代码在我们的laravel项目上是一点问题没有,但是在webman框架使用却出现了事务回滚失败的问题.

问题的原因

其实这个问题还是因为小编没有认真阅读官方文档导致的,而上面的代码导致了一个什么错误让回滚失效的呢?

当事务中操作模型时,特别需要注意模型是否设置了连接。如果模型设置了连接开启事务的时候要指定连接,否则事务无效(think-orm类似)。例如

<?phpnamespace app\model;
use support\Model;class User extends Model
{// 这里给模型指定了连接protected $connection = 'mysql';protected $table = 'users';protected $primaryKey = 'id';}

当模型指定了连接时,开启事务、提交事务、回滚事务必须指定连接

Db::connection('mysql')->beginTransaction();
try {// 业务处理$user = new User;$user->name = 'webman';$user->save();Db::connection('mysql')->commit();
} catch (\Throwable $exception) {Db::connection('mysql')->rollBack();
}

排错之路

通过代码是无法发现问题的,小编通过打开mysql 查询日志general_log来观察执行的sql

打开查询日志配置

[mysqld]
general_log = ON
# 这个日志文档路径必须要有权限写入,否则general_log打开失败
general_log_file = /path/to/your/logfile.logSHOW VARIABLES LIKE 'general_log%';

将 general_log 设置为 ON表示启用查询日志,general_log_file 指定了日志文件的路径,重启 MySQL 服务器:在修改了配置文件后,需要重启 MySQL 服务器以使更改生效。查看日志文件:启用查询日志后,MySQL 会将所有执行过的 SQL 语句记录到指定的日志文件中。您可以查看该文件以获取所有 SQL 语句以及它们对应的连接信息。

查询日志

从上面的日志我们可以看到,事务和业务sql对应的线程ID是不一样的,那么这就是事务回滚两个业务sql不启用的原因了

为啥是不同的线程ID呢

线程ID不一样,肯定是两边分别创建了各自的连接,那我们就开始排查.通过查找了,我发现了webman admin 插件所有的model 都继承了Base类,而Base类指定了连接名,这下就破案了,也对应了官方的那句话:当模型指定了连接时,开启事务、提交事务、回滚事务必须指定连接

因此我们正确的代码:

Db::connection('plugin.admin.mysql')->transaction(...)

再看看连接的源码,默认的连接指向我们配置文件`database.php`的default属性值

DB manager 源码:

/*** Get a database connection instance.** @param  string|null  $name* @return \Illuminate\Database\Connection*/public function connection($name = null){[$database, $type] = $this->parseConnectionName($name);$name = $name ?: $database;// If we haven't created this connection, we'll create it based on the config// provided in the application. Once we've created the connections we will// set the "fetch mode" for PDO which determines the query return types.if (! isset($this->connections[$name])) {$this->connections[$name] = $this->configure($this->makeConnection($database), $type);}return $this->connections[$name];}/*** Parse the connection into an array of the name and read / write type.** @param  string  $name* @return array*/protected function parseConnectionName($name){$name = $name ?: $this->getDefaultConnection();return Str::endsWith($name, ['::read', '::write'])? explode('::', $name, 2) : [$name, null];}/*** Make the database connection instance.** @param  string  $name* @return \Illuminate\Database\Connection*/protected function makeConnection($name){$config = $this->configuration($name);// First we will check by the connection name to see if an extension has been// registered specifically for that connection. If it has we will call the// Closure and pass it the config allowing it to resolve the connection.if (isset($this->extensions[$name])) {return call_user_func($this->extensions[$name], $config, $name);}// Next we will check to see if an extension has been registered for a driver// and will call the Closure if so, which allows us to have a more generic// resolver for the drivers themselves which applies to all connections.if (isset($this->extensions[$driver = $config['driver']])) {return call_user_func($this->extensions[$driver], $config, $name);}return $this->factory->make($config, $name);}

http://www.ppmy.cn/server/6117.html

相关文章

8.Jetson AGX Orin Ubuntu20.04 gRPC编译安装

Jetson AGX Orin Ubuntu20.04 gRPC编译安装 一、CMake版本检查 grpc编译cmake要求最低版本为3.15。首先&#xff0c;cmake -version 查看当前cmake版本&#xff0c;如果低于3.15&#xff0c;按照以下步骤进行安装。 1.1 卸载已经安装的旧版的CMake sudo apt-get autoremove…

记一次kafkakerberos认证问题

1&#xff0c;报错信息 排查思路&#xff1a;检查kerberos配置文件 kerberos.kafka.principalkafka/huawe_baseSECURITY.COM kerberos.kafka.keytabPath/etc/huawe_base.keytab kerberos.kafka.krb5ConfPath/etc/krb5.conf但是查看kafka_client_jass.conf文件&#xff0c;发现…

深度学习驱动的流体力学计算与应用

在深度学习与流体力学深度融合的背景下&#xff0c;科研边界不断拓展&#xff0c;创新成果层出不穷。从物理模型融合到复杂流动模拟&#xff0c;从数据驱动研究到流场智能分析&#xff0c;深度学习正以前所未有的力量重塑流体力学领域。近期在Nature和Science杂志上发表的深度学…

NineData正式将SQL开发正式升级为数据库DevOps

NineData SQL 开发早期主要提供 SQL 窗口&#xff08;IDE&#xff09;功能&#xff0c;产品经过将近两年时间的打磨&#xff0c;新增了大量的企业级功能&#xff0c;时至今日已经服务了上万开发者&#xff0c;覆盖了数据库设计、开发、测试、变更等生命周期的功能。 为了让企业…

学习大数据,所需要的linux基础(1)

文章目录 linux入门概述Linux和Windows的区别CentOS下载地址 Linux文件与目录结构Linux文件Linux目录结构 VI/VIM编辑器vi/vim是什么测试数据集准备一般模式编辑模式指令模式模式间转换 网络配置和系统管理操作查看网络IP和网关配置网络和ip地址ifconfig配置网络接口修改ip地址…

【opencv】dnn示例-scene_text_detection.cpp 场景文本区域检测

模型下载&#xff1a; - DB_IC15_resnet50.onnx: url: https://drive.google.com/uc?exportdowload&id17_ABp79PlFt9yPCxSaarVc_DKTmrSGGf sha: bef233c28947ef6ec8c663d20a2b326302421fa3 recommended parameter setting: -inputHeight736, -inputWidth1280; description…

【计算机网络】网络协议

概述 网络协议&#xff1a;网络协议是为网络中数据的传输和交换建立的一种规则、标准或者约定。 就像公共交通系统&#xff0c;开通了很多道路之后&#xff0c;驾驶员、行人等都需要遵守交通规则&#xff0c;来确保交通的正常运转。 网络中的协议就想交通系统中的交通规则&…