首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数据库连接是全局的还是单例的?

问数据库连接是全局的还是单例的?
EN

Stack Overflow用户
提问于 2008-09-25 00:56:28
回答 9查看 56.6K关注 0票数 81

在PHP中使用单例而不是全局数据库连接有什么好处?我觉得使用单例而不是全局会使代码变得不必要地复杂。

使用Global编写代码

代码语言:javascript
复制
$conn = new PDO(...);

function getSomething()
{
    global $conn;
    .
    .
    .
}

使用单例编写代码

代码语言:javascript
复制
class DB_Instance
{
    private static $db;

    public static function getDBO()
    {
        if (!self::$db)
            self::$db = new PDO(...);

        return self::$db;
    }
}

function getSomething()
{
    $conn = DB_Instance::getDBO();
    .
    .
    .
}

如果有比全局或单例更好的初始化数据库连接的方法,请提及它,并描述它相对于全局或单例的优势。

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2008-10-20 19:37:20

我知道这很古老,但Dr8k的答案几乎就在那里。

当你在考虑写一段代码时,假设它会发生变化。这并不意味着你会假设它在未来的某个时候会发生什么样的改变,而是某种形式的改变将会发生。

把它作为一个目标,减轻未来做出改变的痛苦:全局是危险的,因为它很难在一个单一的地点进行管理。如果我想在将来让数据库连接上下文感知,该怎么办?如果我希望它每5次被使用一次就自动关闭并重新打开该怎么办?如果我决定为了扩展我的应用程序,我想使用10个连接池呢?或者可配置的连接数量?

单例工厂为您提供了这种灵活性。我只需要很少的额外复杂性就可以设置它,并且获得的不仅仅是对相同连接的访问;我能够以一种简单的方式更改该连接稍后传递给我的方式。

注意,我说的是单例工厂,而不是简单的单例工厂。单例和全局之间几乎没有区别,这是真的。正因为如此,没有理由使用单例连接:当您可以创建常规全局连接时,为什么还要花费时间进行设置呢?

工厂为您提供的是获取连接的原因,以及一个单独的位置来决定您将获得哪些连接(或连接)。

示例

代码语言:javascript
复制
class ConnectionFactory
{
    private static $factory;
    private $db;

    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    public function getConnection() {
        if (!$this->db)
            $this->db = new PDO(...);
        return $this->db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

然后,在6个月内,当你的应用程序非常出名,并且你决定你需要多个连接时,你所要做的就是在getConnection()方法中实现一些池化。或者,如果您决定需要一个实现SQL日志记录的包装器,您可以传递一个PDO子类。或者,如果您决定在每次调用时都想要一个新的连接,您可以这样做。它是灵活的,而不是僵化的。

16行代码,包括大括号,这将为您节省数小时、数小时和数小时的重构时间。

请注意,我不认为这是“特性爬行”,因为我在第一轮中没有做任何特性实现。这是“未来爬行”的界限,但在某种程度上,“为今天的明天编码”永远是一件坏事的想法对我来说并不成立。

票数 105
EN

Stack Overflow用户

发布于 2008-09-25 01:05:47

我不确定我是否能回答你的具体问题,但我想建议,如果这对于基于web的系统来说,全局/单一连接对象可能不是最好的主意。DBMS通常被设计为以高效的方式管理大量的唯一连接。如果您使用的是全局连接对象,则您将执行以下操作:

  1. 强制您的页面按顺序执行所有数据库连接,并终止异步页面加载的任何尝试。
  2. 可能会在数据库元素上保持打开锁的时间超过必要的时间,从而降低整个数据库的速度,使您的数据库可以支持的同时连接的总数减少,并阻止新用户访问资源。

我相信还有其他潜在的后果。请记住,此方法将尝试为访问该站点的每个用户保持数据库连接。如果你只有一个或两个用户,没问题。如果这是一个公共网站,你想要流量,那么可伸缩性就会成为一个问题。

编辑

在较大规模的情况下,每次访问数据库都会创建新的连接,这可能是不好的。然而,答案并不是创建一个全局连接并将其用于所有事情。答案是连接池。

使用连接池,可以维护许多不同的连接。当应用程序需要连接时,将检索池中的第一个可用连接,然后在其工作完成后返回到池中。如果请求连接但没有可用的连接,则将发生以下两种情况之一: a)如果未达到允许的最大连接数,则打开新的连接,或者b)强制应用程序等待连接变为可用。

注意:在.Net语言中,缺省情况下,连接池由ADO.Net对象处理(连接字符串设置所有必需的信息)。

感谢Crad对此发表评论。

票数 16
EN

Stack Overflow用户

发布于 2011-12-13 08:35:10

创建单例方法是为了确保任何类只有一个实例。但是,因为人们使用它作为全球化的捷径,它成为众所周知的懒惰和/或糟糕的编程。

因此,我会忽略全局和单例,因为它们都不是真正的OOP。

您正在寻找的是依赖注入。

您可以在http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection上查看与依赖注入(带有示例)相关的易于阅读的基于PHP的信息

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/130878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档