【问题标题】:PHP transaction handling with multiple mysqli object具有多个 mysqli 对象的 PHP 事务处理
【发布时间】:2012-03-30 13:18:33
【问题描述】:

假设我们有两个独立的类,每个类都有一个 mysqli 对象用于数据库操作。

class A{
  protected $mysqliObject;
  public function __constructor(){
    $this->mysqliObject=new mysqli(...)
  }
  public function doSomething(){
    $this->mysqliObject->query(...);
  }
}
class B{
  protected $mysqliObject;
  public function __constructor(){
    $this->mysqliObject=new mysqli(...)
  }
  public function doSomething(){
    $this->mysqliObject->query(...);
  }
}

doSomething() 方法使用$mysqliObject 进行数据库查询(SELECT、UPDATE、DELETE 等...)。我想在外面做以下事情:

// Start point
$aObject=new A();
$bObject=new B();
$aObject->doSomething();
$bObject->doSomething();
// End point

...但是如果其中任何一个查询失败,我想回滚这两个查询。我该怎么做?

  • 能否在“起点”创建一个全新的mysqli 对象,并使用它在“终点”提交或回滚class Aclass B 的数据库查询?
  • 我是否必须在外部创建,并将相同的$mysqliObject 传递给class Aclass B__constructor(),并使用它来回滚或提交(外部)。

希望看到更多与赞成者有关的技术。

【问题讨论】:

    标签: php database transactions mysqli


    【解决方案1】:

    您拥有的每个数据库连接对象都代表与数据库的不同连接,即使该连接是与同一数据库服务器的连接。每个连接彼此完全独立,因此在一个连接中启动的事务对另一个连接是不可见的。

    如果您的所有数据库访问都针对同一台服务器,那么只需创建一个连接并将其传递给需要访问该连接的任何对象。然后事务将是应用程序范围的。

    class ClassThatNeedsDbAccess
    {
        protected $connection = NULL;
    
        protected function doQuery ($query)
        {
            return ($this -> connection -> execute ($query));
        }
    
        public function __construct (PDO $connection)
        {
            $this -> connection = $connection;
        }
    }
    
    class OtherClassThatNeedsDbAccess extends ClassThatNeedsDbAccess
    {
    }
    
    $myDb = new PDO ('dsn_goes_here');
    
    $obj1 = new ClassThatNeedsDbAccess ($myDb);
    $obj2 = new OtherClassThatNeedsDbAccess ($myDb);
    

    如果您正在与不同的数据库服务器通信,那么您可能应该将所有连接包装在一个可以协调数据库活动的对象中。该对象负责跟踪哪个数据库连接有一个正在运行的事务。

    【讨论】:

    • 基本上我的问题是要问/针对不同的方法。也许我只是想稍微作弊,然后把 OOP 扔出窗外。我会照你说的做。
    • 祝你好运。这可能适用于虚构的程序,但在实践中你会遇到commands are out of sync。这个问题清楚地说明了 mysqli 的使用。
    【解决方案2】:

    使用一个 MySQL 对象 - 连接所有业务逻辑...看看单例模式。您可以将其传递给构造函数,也可以使用静态类方法获取 mysql 对象。

    那么你的问题是你从哪里开始结束事务,连接必须相同。最好将其抽象为一些通用的数据库访问层。

    【讨论】:

    • 谢谢,有趣的文章。所以建议只是将数据库对象注入?
    • 是的,依赖注入是要走的路。将同一个对象注入所有依赖项将具有与单例相同的效果,如果您稍后发现其中一个依赖项需要不同的连接,那么您只需为其提供不同的数据库对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 2017-02-07
    • 1970-01-01
    相关资源
    最近更新 更多