php - 单例类和mysqli事务

标签 php mysql mysqli transactions

我有一个单例类 DataBase 用于共享数据库连接:

class DataBase
{
  private static $mysqli;

  final private function __construct() {}

  public static function getInstance()
  {
    if (!is_object(self::$mysqli)) self::$mysqli = new mysqli($H,$U,$P,$B);
    return self::$mysqli;
  }

  private function __destruct()
  {
    if (self::$mysqli) self::$mysqli->close();
  }

  private function __clone() {} //no cloning in singleton
}

我在许多其他类中使用这个单例对象,并在每个类构造函数中从单例中检索数据库连接,例如:

class Customer
{
  public $db;

  function __construct()
  {
    $this->db=DataBase::getInstance();
  }

  public function create()
  {
    $this->db->query('INSERT INTO customers SET ... WHERE id=100'); //e.g.
  }

}

class Product
{
  public $db;

  function __construct()
  {
    $this->db=DataBase::getInstance();
  }

  public function create()
  {
    $this->db->query('INSERT INTO products SET ... WHERE id=200'); //e.g.
  }
}

因为我所有的类实际上共享单例类给定的相同连接,我的问题是我可以从一个类开始数据库事务并从另一个类回滚/提交它。实际上我的意思是,下面的代码是一个正确创建的数据库事务,用于在一个数据库事务中创建客户和产品(在后面建模数据库记录的类):

$Customer=new Customer();
$Customer->db->begin_transaction();
...
$Customer->create();
...
$Product=new Product();
$Product->create();
...
$Product->db->commit();

这段代码如何在多用户环境中工作,在多用户环境中,所有用户都共享来自 sigleton 类的相同连接?

最佳答案

正如@Marc B 提到的,事务是基于连接的,因此通常您能够在两个不同的对象中启动和提交事务。

但是,您应该确保您没有使用持久连接(阅读更多关于 PHP 和 mysqli 处理连接的信息 http://php.net/manual/en/mysqli.quickstart.connections.php 。持久连接在脚本之间汇集并可能使您的应用面临风险交易干扰。

此外,请记住某些语句会导致隐式提交(如 http://php.net/manual/en/mysqli.quickstart.transactions.php 所述)。 您还应该验证,您与数据库的连接在脚本执行期间不会超时(在某些情况下可能会发生)。我将从检查 MySQL 的 wait_timeout http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_wait_timeout 开始设置。

IMO,您还应该认真考虑应用程序的设计。我坚信,DB 对象应该只在 Model 对象中可用,并且只能从它们内部调用,而不是在代码中的任何地方显式调用。

如果您决定考虑事务 - 请记住在您的数据库类中放置适当的方法(如在对象销毁时添加自动提交 (TRUE) 和回滚 (),如果事务已启动)。安全总比后悔好。

我强烈建议您选择(或更改您的数据库引擎)InnoDB(对表锁定和事务的强大支持)- 在 The InnoDB Transaction Model and Locking 中阅读更多相关信息.此处的文档中还有大量有关交易的有用信息:Mysql transactions and locking .

关于php - 单例类和mysqli事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25515710/

相关文章:

mysql - 进行波浪变换的正确方法

php - 需要评估 Joomla 是否适合 Web 应用程序需求

PHP mysqli 只显示一个用户

php - 在PHP中加载数据infile不起作用

php - 使用 mySqli 清理数据

php - 使用 PHP 压缩的文件在提取后生成 cpgz 文件

mysql - 在 OSX El Capitan、RVM 上为旧版 Rails 应用程序安装 mysql gem - MySQL dmg/brew

php - PHP 中的 mysqli - bind_result 总是返回 null

php - 有没有办法将当前日期添加到 php 中接收到的 JSON?

php - 使用 PHP 在 Curl 中将 .PEM 和 .KEY 作为字符串传递