6

示例应用程序,具有员工信息并被工资单和 pos 等不同应用程序访问。我在一个数据库中有员工数据,工资单数据和 pos 分别在不同的数据库中。

我有一个像下面这样的数据库连接类,所以每次我想连接到一个数据库时,我都会这样做$conn = Database::getInstance(db1)

效果很好,但基本上超级慢。使应用程序运行非常缓慢。关于为什么会这样或更好的替代想法的任何提示?

任何帮助将不胜感激

<?php    
class Database {
        private $db;
        static $db_type;
        static $_instance;

        private function __construct($db){
            switch($db) {
                case "db1":
                  try{
                      $this->db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
                case "db2":
                  try{
                      $this->db = new PDO("mysql:host=" . DB_HOST_2 . ";dbname=" . DB_NAME_2, DB_USER_2, DB_PASSWORD_2);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
            }
            self::$db_type = $db;

        }

        private function __clone(){}

        static function getInstance($db_type){
            if(!(self::$_instance) || $db != self::$db_type){
                self::$_instance = new self($db_type);
            }
            return self::$_instance;
        }
    }
?>
4

5 回答 5

1

不要不断地创建新对象。发生的情况是,每次您请求另一种数据库类型时,您都是通过 new 关键字重新创建它(尽管如果没有看到使用它的代码就很难确认)。

$_instance 是一个静态成员,因此当您更改数据库类型时,您会不断地覆盖它。$db_type 也是如此

虽然这对你正在做的事情来说有点过头了(为什么每个数据库不只有两个变量?),你可以尝试更多这样的事情:

<?php    
class Database {
        private $db;
        static $db_types;


        private function __construct($db){
            switch($db) {
                case "db1":
                  try{
                      $db_types[$db] = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
                case "db2":
                  try{
                      $db_types[$db] = new PDO("mysql:host=" . DB_HOST_2 . ";dbname=" . DB_NAME_2, DB_USER_2, DB_PASSWORD_2);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
            }


        }

        private function __clone(){}

        static function getInstance($db_type){
            if(!inarray($db_types[$db_type]){
                $db_types[$db_type] = new self($db_type);
            }
            return $db_types[$db_type];
        }
    }
?>

注意:语法可能已关闭。只是想展示这种模式。

于 2012-11-02T01:16:19.750 回答
1

有了这个设计。如果您更改数据库,那么它会破坏与先前数据库的连接。

为每个连接创建单独的对象,然后在连接对象之间切换。

此外,出于同样的原因,这不是线程安全的。如果多个功能同时达到此功能,则可以在完成加载之前断开另一个功能。

您真的应该为每个函数创建一个新的连接对象,而不是在函数或其他对象之间共享它。

于 2012-11-02T01:16:44.833 回答
1

除了您不断切换连接的事实之外,我不明白为什么这会使事情变慢。我在这里唯一可以建议的是允许多个连接而不是切换它们:

class Database {
   protected static $connections;

   protected $activeConnections = array();

   protected static $instance;

   protected function __construct() {

   }

   public static loadConnections(array $connections) {

      self::$connections = $connections;
   }

   public function getConnection($name)
   {
      if(!isset($this->activeConnections[$name]) {
          if(!isset(self::$connections[$name]) {
             throw new Exception('Connection "' . $name . '" is not configured.');
          }

           $this->activeConnections[$name] = new PDO(
              self::$connections[$name]['dsn'],
              self::$connections[$name]['username'], 
              self::$connections[$name]['password']
          ); 

      }

      return $this->activeConnections[$name];
   }
}

// usage

Database::loadConnections(array(
   'db1' => array(
       'dsn' => "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME,
       'user' => DB_USER,
       'password' => DB_PASSWORD,
    ),
    'db2' => array(
       'dsn' => "mysql:host=" . DB_HOST2 . ";dbname=" . DB_NAME2,
       'user' => DB_USER2,
       'password' => DB_PASSWORD2,
)));

$conn1 = Database::getInstance()->getConnection('db1');
$conn2 = Database::getInstance()->getConnection('db2');

使用类似的东西,您实际上可以一次管理多个打开的连接,并且它们是延迟加载的 - 这意味着您实际上不会实例化 PDO 连接,直到您使用Database::getConnection类似的方式您可以随时注入额外的 DSN 和凭据。就个人而言,我会将这些表单配置直接加载到类中,而不是使用类中的常量对它们进行硬编码。那么你可以这样:

// gives us an array
$config = Config::load('path/to/db/config.yml');

Database::loadConnections($config);
于 2012-11-02T01:28:44.090 回答
0

检查 DB_HOST 和 DB_HOST_2 的值。以前我发现 MySQL 使用“127.0.0.1”连接非常慢,但使用“localhost”立即连接。

这取决于您的服务器的设置方式,但只是认为它可能会有所帮助。

于 2012-11-02T01:20:22.320 回答
0

如何将其更改为也使用延迟加载。您不需要连接到承包商中的数据库。仅在首次需要数据库时进行连接。这样,如果页面只使用其中一个连接,则不需要等待其他数据库。

于 2012-11-02T01:14:31.840 回答