Singleton有多个数据库

时间:2012-11-02 01:02:06

标签: php singleton multiple-databases

示例应用程序,具有员工信息并由不同的应用程序(如工资单和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;
        }
    }
?>

5 个答案:

答案 0 :(得分: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];
        }
    }
?>

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

答案 1 :(得分:1)

采用这种设计。如果更改数据库,则会破坏与先前数据库的连接。

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

此外,出于同样的原因,这不是线程安全的。如果多个函数同时发生这种情况,可以在完成加载之前断开另一个函数。

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

答案 2 :(得分: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和凭证随时可用。就个人而言,我会将表单配置加载到类中,而不是使用常量int类对其进行硬编码。那么你可以这样:

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

Database::loadConnections($config);

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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