1

所以我终于开始重构我的 PHP 办公应用程序的基础:我添加了基于单例 PDO 类的新功能,我计划在整个应用程序中部署它。它非常简单且有效(目前),因为它应该:

class DB {

    protected static $instance;
    protected function __construct() {}
    public static function getInstance()
    {

        if( empty( self::$instance ) )
        {
            $dsn =  'pgsql:host=' . Config::$a .
                    ';dbname='    . Config::$b .
                    ';port='      . Config::$c .
                    ';connect_timeout=15';            
            $db_user = Config::$d;             
            $db_pass = Config::$e;

            try
            {
                self::$instance = new PDO( $dsn, $db_user, $db_pass );
                self::$instance->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
            }  
            catch( PDOException $e )
            {  
                new Log( 6, "DB Class failed to connect to dbase: $e" );
            }                          
        }
        return self::$instance;
    }
}

今天下午我要告诉我的一个朋友,他是一个 .NET 程序员,关于这个单例 db-connection 类,他警告我使用单例连接到数据库会导致线程问题。

我必须说我已经想到了:几个用户将使用该应用程序,并且几乎所有功能都与(多个)数据库查询相关。两个用户同时执行一个查询并不是不可想象的。

PDO(或 PHP,或 Apache(在办公室),或 Nginx(在家测试环境))是否能够处理这个问题?也许为每个用户提供了一个新实例?也许我应该将此单例与将为每个查询/更新/插入/删除锁定数据库以避免线程问题的事务一起使用?或者也许我的朋友错了,我不必担心?

感谢任何见解!

4

2 回答 2

6

不要担心使用单例来建立连接。

每个 php 脚本请求都有自己的线程。我的意思是,如果同时发生两个请求,Web 服务器将在两个不同的线程中执行你的单例,所以你最终将有两个不同的对象处理数据库连接。

于 2013-01-27T20:11:08.680 回答
1

Josh Lockhart 在http://www.phptherightway.com/pages/Design-Patterns.html上恢复得很好

当我们需要确保在 Web 应用程序的整个请求生命周期中只有一个类的单个实例时,单例模式很有用。这通常发生在我们拥有全局对象(例如配置类)或共享资源(例如事件队列)时。

因此,如果您请求一个脚本,并且该脚本对 DB 进行多次访问(或调用另一个访问 DB 的脚本),则使用 Singleton 将具有优势。=) 很明显,最好通过请求(例如,通过使用存储过程)来阻止一次以上的访问。

于 2017-01-25T04:22:58.917 回答