No way to close database connection

Created on 28 June 2024, 2 months ago

Problem/Motivation

Drupal\Core\Database\Database::closeConnection() does not actually close connection.

Currently the Database::closeConnection() works like follows.

unset(self::$connections[$key]);
// Force garbage collection to run. This ensures that client connection
// objects and results in the connection being closed are destroyed.
gc_collect_cycles();

I think the intention was to trigger connection destructor which should close the actual DB connection by removing PDO object. However this does not work as PHP won't call a destructor if there are any references to the object. In this case references likely come from services that depend on @database because they keep reference to Drupal\Core\Database\Connection in their class properties.

Steps to reproduce

Drupal\Core\Database\Database::closeConnection();
sleep(60);

While the Drupal is "sleeping" check open connections to your database with tools like pg_stat_activity.

Proposed resolution

Remove Database::closeConnection() as it basically useless.

Add \Drupal\Core\Database\Connection::closeClientConnection() and \Drupal\Core\Database\Connection::openClientConnection() methods.

Those can look like follows.

public function openClientConnection(): void {
  $this->connection = self::open($this->connectionOptions);
}

public function closeClientConnection(): void {
  $this->connection = NULL;
}
🐛 Bug report
Status

Active

Version

10.3

Component
Database 

Last updated less than a minute ago

  • Maintained by
  • 🇳🇱Netherlands @daffie
Created by

🇷🇺Russia Chi

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @Chi
  • 🇷🇺Russia Chi

    The use case for closing and reopening connections is to keep their number under limit. The limit can be easily exceeded when you have many PHP processes that are doing slow operations, i.e. HTTP requests to external servers.
    So theoretically you could deal with this like follows.

    $this->database->closeClientConnection();
    
    $this->httpClient->get('https://some.very/slow/service');
    
    $this->database->openClientConnection();
    
Production build 0.71.5 2024