何时打开/关闭数据库连接?

Win*_*Too 1 postgresql odbc

我在Windows上通过VB.NET /ODBC使用PostgreSQL数据服务器,这对于存储/操作数据来说似乎是非常可靠和高度可用的解决方案.
作为初学者,我对何时打开/关闭数据库连接存有疑虑.

例如,我可以在程序启动时打开连接,并在程序执行期间保持打开状态,这可能是几天甚至几个月的持续时间.在这种情况下,我传输连接参考以用于程序中的所有读/写功能.

或者,在其他情况下,我可以打开/关闭每个函数调用或数据库操作的连接,这不需要很长时间,但会带来许多打开/关闭的情况.

现在我想从有经验的用户那里得到更好的推荐方式.

1)在程序执行的所有时间保持打开的连接.
2)每次需要读取/保存数据时连接/关闭.

第二个但相关的问题是当我打开这样的数据库连接时:

    Dim conn As New OdbcConnection
    conn.ConnectionString = "Dsn=" + dbDsn + _
                            ";database=" + mydatabase + _
                            ";server=" + dbServer + _
                            ";port=" + dbPort + _
                            ";uid=" + dbUser + _
                            ";pwd=" + dbPass
    conn.Open()
    ... etc...
Run Code Online (Sandbox Code Playgroud)

这是一种在程序中稍后找到使用"conn"引用的连接打开确切数据库的方法吗?

Cra*_*ger 13

保持连接很长时间,但保持交易尽可能短.

如何查找数据库

SELECT current_database()

请参阅postgresql信息函数

具有容错功能的长连接

不要经常打开和关闭连接.挂在他们身上,但要准备让他们从你身下消失,例如:

  • 如果重新启动数据库或服务器
  • 如果您和服务器之间存在状态防火墙/路由器,可能会在一段时间后忘记空闲连接跟踪关联
  • 如果数据库管理员因任何原因故意关闭您的连接

您的应用必须优雅地应对连接变得无法使用,并准备在建立新连接后重新尝试操作.确保限制重试次数,这样就不会永远循环,反复使用相同的故障锤击数据库服务器.

由于连接可能随时变为无效,因此必须始终检查绝对每个数据库操作的错误代码,除非您的语言在数据库操作失败时可以抛出异常.如果可以使用异常,则只需将整个数据库操作序列包装在一个try/catch中.

如果您的应用程序非常简单且无需用户友好,则可以告诉用户您丢失了连接并要求他们重新启动应用程序.我个人认为,如果你选择这种方法,你会后悔它,但它确实使错误处理更容易.

如果您的应用程序需要同时连接多个连接,请使用连接池或重新设计以在单个连接上对操作进行排队.

具有容错和重试的短事务

如果您愿意,可以长时间保持联系,您应该尽可能缩短交易时间.长时间运行的事务会导致某些数据库系统出现问题,包括PostgreSQL - 它们会降低效率,增加锁定问题的风险等.不要让事务在用户"思考时间"上保持打开状态 - 即暂停用户交互 - 如果可能的话.如果您必须保持交易开放,请尝试暂停,如果他们决定在填写该表单的中途休假,则将用户退回到会话到期的开始.如果你认为我在开玩笑,你还没有花足够的时间来维护生产应用程序.

您的应用程序应该准备好让任何数据库操作失败并能够重新尝试它.在数据库语句成功运行后,不要丢弃应用程序对任务的了解; 保留它直到整个事务成功提交.这样,如果您遇到序列化失败,您的tx被服务器取消等,您可以重新发布整个事务.

想象一下,你写了一些典型的线性数据库访问代码(伪代码,我不会说Visual Basic),如下所示:

BEGIN;
value = get_value1_from_user();
UPDATE something SET field = :value;
value = get_value2_from_user();
UPDATE somethingelse SET otherfield = :value;
COMMIT;
Run Code Online (Sandbox Code Playgroud)

现在想象如果第二次UPDATE失败会发生什么.该COMMIT不会发生-如果你尝试运行它,它会做ROLLBACK,而不是-你不知道用户输入什么,get_value1_from_user()所以你不能重试.

写一些类似的东西通常更明智:

value1 = get_value1_from_user();
value2 = get_value2_from_user();
committed = false;
retries = 3;
do:
    try:
        BEGIN;
        UPDATE something SET field = :value1;
        UPDATE somethingelse SET otherfield = :value2;
        COMMIT;
        committed = true;
    catch ...:
        retries = retries - 1;
        log "Failed to commit (sometask) because of (error message from database), "+retries+" left"
while not committed and retries > 0;
if not committed:
    print "Tell the user I couldn't save their work"
end if;
Run Code Online (Sandbox Code Playgroud)

当然,您希望对重试很聪明.发生故障后,检查以确保连接仍然存在并重新建立,然后重试(如果不存在).检查你的语句失败的原因 - 重新尝试语法错误的语句是没有意义的.这就是为什么SQLSTATE,在不检查消息文本的情况下区分不同类型的错误.

永远不要将错误消息文本作为一种决策方式进行检查,因为消息会被翻译并且可以在不同版本之间进行更改.

没有"经过验证"的连接

在数据库开发方面不熟练的开发人员可以通过在进行操作之前验证数据库连接来节省大量麻烦.他们发布了一个SELECT 1或者什么,并根据连接可用的结论得出结论,因此在尝试下一个操作时不会失败.

这是假的."验证"和下一次操作之间存在固有的竞争条件.不仅如此,只是因为简单的验证操作成功并不意味着下一个非平凡的声明不会失败.您的应用应该跟踪在事务发生期间所做的所有更改,直到提交为止,并且能够在事务失败时重试.

另一种方法是告诉用户"oops,失败.重新输入所有更改,然后重试".有时这实际上是正确的事情,例如当使用乐观锁定策略时,两个正在进行的更改会发生冲突,并且您无法以编程方式安全地合并它们.不过,通常在幕后重试通常会更好.