没有不值得去解决的问题,也没有不值得去学习的技术!

在 Laravel 6 的多个数据库连接(MySQL)中使用事务

当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入成功后,第 2 张表(对应连接 db)中插入失败,事务回滚,所有表中皆未插入数据。符合预期
1、现在一个 API,需要插入 4 张表,第 1 张表为数据库 A 中的表,其他 3 张表为数据库 B 中的表,且第 1 张表的主键会插入至第 2 张表中。已经配置了 2 个数据库连接。分别为 wordpress、db。在一个应用程序中建议仅连接一个数据库,但是现在是历史遗留问题。 2、现有的代码实现如下。仅在数据库 B 中的 3 张表的插入时使用了数据库事务。如果事务回滚,则数据库 A 中的表的已插入数据变为了脏数据。


$wpTheme = Theme::create([
	'name'          => $name,
	'custom_name'   => $custom_name,
	'content'       => $content,
	'is_original'   => $isOriginal,
	'original_theme_name' => $config['name'],
]);

DB::beginTransaction();
try {

	$themeInstallation = new ThemeInstallation();
	$themeInstallation->theme_store_theme_id = $saasThemeConfig[$name]['id'];
	$themeInstallation->theme_id = $name;
	$themeInstallation->wp_theme_id = $wpTheme->id;
	$themeInstallation->theme_custom_name = $custom_name;
	$themeInstallation->save();

	$themeInstallationVersion = new ThemeInstallationVersion();
	$themeInstallationVersion->theme_installation_id = $themeInstallation->id;
	$themeInstallationVersion->theme_store_theme_id = $saasThemeConfig[$name]['id'];
	$themeInstallationVersion->theme_store_theme_version_id = $saasThemeConfig[$name]['id'];
	$themeInstallationVersion->save();

	$themeInstallationTask = new ThemeInstallationTask();
	$themeInstallationTask->theme_installation_id = $themeInstallation->id;
	$themeInstallationTask->theme_installation_version_id = $themeInstallationVersion->id;
	$themeInstallationTask->save();

	DB::commit();
} catch(\Throwable $e) {
	DB::rollBack();
	throw $e;
}


3、第 1 张表所对应的模型配置连接如下


class Theme extends Model
{
    protected $connection = 'wordpress';
}


4、第 2、3、4 张表所对应的模型配置连接为默认连接。 5、参考实现:https://laracasts.com/discuss/channels/laravel/transactions-with-multiple-database-connections 。不过,如果 DB::commit() 成功而 DB::connection(‘wordpress’)->commit() 失败会怎样? 在这种情况下,我们无法在 db 中回滚,并且一致性被破坏。 6、先测试事务成功的情形,确认 4 张表皆插入数据成功。 7、当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入成功后,第 2 张表(对应连接 db)中插入失败,事务回滚,所有表中皆未插入数据。符合预期。如图1
当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入成功后,第 2 张表(对应连接 db)中插入失败,事务回滚,所有表中皆未插入数据。符合预期
图1


{
    "message": "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'theme' for key 'theme_installation_theme_id_unique' (SQL: insert into `theme_installation` (`theme_custom_name`, `role`, `processing`, `processing_failed`, `theme_store_theme_id`, `theme_id`, `wp_theme_id`, `updated_at`, `created_at`) values (theme, unpublished, 1, 0, 9, theme, 31, 2022-05-18 10:39:55, 2022-05-18 10:39:55))",
    "code": "23000",
    "status_code": 500,
    "debug": {
        "line": 669,
        "file": "\\.\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php",
        "class": "Illuminate\\Database\\QueryException",
        "trace": {
		}
    }
}


8、当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入成功后,第 2 张表(对应连接 db)中插入成功,第 3 张表(对应连接 db)中插入失败,事务回滚,所有表中皆未插入数据。符合预期。如图2
当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入成功后,第 2 张表(对应连接 db)中插入成功,第 3 张表(对应连接 db)中插入失败,事务回滚,所有表中皆未插入数据。符合预期
图2


{
    "message": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'theme_installation_ide' in 'field list' (SQL: insert into `theme_installation_version` (`update_state`, `processing`, `processing_failed`, `theme_installation_ide`, `theme_store_theme_id`, `theme_store_theme_version_id`, `updated_at`, `created_at`) values (manual_update, 1, 0, 7, 9, 9, 2022-05-18 10:46:32, 2022-05-18 10:46:32))",
    "code": "42S22",
    "status_code": 500,
    "debug": {
        "line": 669,
        "file": "\\.\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php",
        "class": "Illuminate\\Database\\QueryException",
        "trace": {
		}
    }
}


9、当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入失败后,所有表中皆未插入数据。符合预期。如图3
当第 1 张表(对应连接 wordpress、对应 $wpTheme)插入失败后,所有表中皆未插入数据。符合预期
图3


{
    "message": "Array to string conversion",
    "status_code": 500,
    "debug": {
        "line": 419,
        "file": "\\.\\vendor\\laravel\\framework\\src\\Illuminate\\Support\\Str.php",
        "class": "ErrorException",
        "trace": {
		}
    }
}


10、针对问题,如果 DB::commit() 成功而 DB::connection(‘wordpress’)->commit() 失败会怎样?暂时不好模拟,决定留待后续分析处理。  

PHP / Laravel / Yii2 老项目维护与长期技术支持

如果你的 PHP / Laravel / Yii2 项目已经上线,但遇到原开发离职、Bug 长期无人修复、接口不稳定、性能下降、代码难以接手等问题,可以联系我做一次远程技术排查。

适合以下情况:
✅ 老旧 PHP 系统无人维护
✅ Laravel / Yii2 项目 Bug 修复
✅ 后台管理系统小功能迭代
✅ RESTful API 接口排查
✅ MySQL / Redis / Nginx 性能问题
✅ 长期远程兼职维护

可先从一次小问题开始:
✅ 线上报错排查
✅ 接口异常分析
✅ 慢查询与性能瓶颈定位
✅ 代码结构初步评估
✅ 部署环境与日志检查

如需咨询,请联系我,并注明:PHP 维护咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理