使用多个mysqli对象的PHP事务处理


PHP transaction handling with multiple mysqli object

让我们假设我们有两个独立的类,每个类都拥有一个用于数据库操作的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(),然后使用它回滚或提交(外部)吗

希望看到更多的技术与专业的。

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

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

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);

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

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

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