【问题标题】:Laravel 8 DB transaction: is a transaction unique to the controller instance or is it unique to the connection DB name?Laravel 8 DB 事务:是控制器实例独有的事务还是连接数据库名称独有的事务?
【发布时间】:2021-07-19 04:30:48
【问题描述】:

我对 Laravel 比较陌生,我想了解更多关于 API 控制器方法(即在 routes/api.php 中定义)中以下代码的行为。

DB::connection($dbName)->beginTransaction();

假设两个人同时访问服务器并创建了两个控制器实例。现在两个实例都调用DB::connection($dbName)->beginTransaction();) 并在提交前执行一些代码。

为了更清楚地描述这种情况,两个人 A 和 B 都访问同一个 Laravel 服务器,具有同一个控制器类的两个实例。两个控制器实例都从同一个 IP 地址访问同一个 DB,并执行涉及beginTransaction 的相同代码段。

根据我目前的信息,有两种可能发生的事情:

(1) 它们被视为两个不同的事务,诸如 lastInsertId 之类的东西是分开维护的。这是所需的行为,但我无法理解控制器的两个不同实例是如何在内部识别的。根据对 Laravel 源代码的粗略查看,它似乎只读取特定数据库连接的配置文件,这对于控制器的两个实例都是相同的。

(2) 它们被视为相同的事务,这不是期望的行为。我将不得不想办法让它像(1)中描述的那样工作

目前我没有足够的环境来准确测试并发控制器实例的行为,所以我必须在这里提出问题。

我已阅读 https://laravel.com/docs/8.x/database#database-transactions,但它并没有告诉我们是 (1) 还是 (2)。

【问题讨论】:

  • 作为一个不了解 laravel 的人,我会在两个连接中都使用 select CONNECTION_ID() (mysql too)。如果您最终得到不同的数字,则为 (1)。
  • 每个并发请求都在它自己的 PHP 线程/进程中处理,并且每个事务都与其他事务隔离。每个控制器实例都将存在于该线程/进程中。 PHP 不像 Java EE 或 .NET,其中服务器也是对象的容器,因此可以跨请求共享对象
  • @apokryfos 谢谢你的回答。这是否意味着 PHP 的默认行为必须是 case (1) 有或没有 Laravel?
  • 是的,在 PHP 中,每个请求都是一个独立的实体,它在自己的“沙箱”中初始化任何东西。有 ways 在 PHP 进程之间共享信息,但它们的级别非常低,在实践中很少使用。还有一些方法可以将 MySQL 连接池化,但即使您每次从池中获取连接时都使用这些连接,它也会被重置。

标签: mysql laravel transactions


【解决方案1】:

第一种情况

事务甚至不是 Laravel 的一部分——它们是 SQL 的一部分。 Laravel 只调用 SQL。

同样在 PHP 中,每个请求都是通过生成一个新的脚本实例来单独处理的。因此两个请求之间没有变量共享。

【讨论】:

    猜你喜欢
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 1970-01-01
    相关资源
    最近更新 更多