framework: PDO Too many connections when running test suite
- Laravel Version: 5.4.16
- PHP Version: 7.1
- Database Driver & Version: MySQL
Description:
I have a test suite which now has 140 tests. Each of my tests uses the DatabaseMigrations trait along with a dedicated database solely for tests to run against.
When PHP Unit gets to the last test it fails with the following error:
Caused by
Doctrine\DBAL\Driver\PDOException: SQLSTATE[08004] [1040] Too many connections
I can run this test individually and it passes fine.
After finding this issue (https://github.com/laravel/framework/issues/10619#issuecomment-151075567) I tried the following but the problem still persists:
- Added the
PDO::ATTR_PERSISTENT => false
option to my test database connection entry - Added the following code to the DatabaseMigrations trait:
$this->beforeApplicationDestroyed(function () {
$this->artisan('migrate:rollback');
foreach ($this->app->make('db')->getConnections() as $connection) {
$connection->disconnect();
}
});
Steps To Reproduce:
N/A
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 25 (13 by maintainers)
What exactly do you mean reused? Connection is closed after each test, and until its closed new one opens up…
I tested this using Innotop on my local machine (installed from homebrew), I have 69 test total, and each test class uses
DatabaseMigrations
trait and Innotop showed 69 connections. I guess PHPUnit is fast so connections are not closed ASAP.I found this post about this issue.
After that
max_connection
stats were ±3.I believe the problem is that the connection should be reused (or a few of them pooled), not that the database has a too low max_connections value.
Adding this option in the testing database solve the problem in Laravel 5.5.2
The best way we find to fix this issue was to move the test to sqlite driver:
and my phpunit.xml
With this we saved around 90% of time running our test cases.
Its problem with
max_connections
.Naive solution is to increase
max_connections
using (run query)To check current
max_connections
I tested
max_connections = 10
and run 60 tests and it failed with@GuidoHendriks was right, I’ve just replaced:
by:
in the
RefreshDatabase
trait, and now it works like a charm! I wrote a PR (#22569) to fix that.I just noticed that both
RefreshDatabase
andDatabaseTransactions
use similar methods calledbeginDatabaseTransaction
. They do exactly the same, except for 1 thing:DatabaseTransactions
not only rolls back, but disconnects as well. WhereRefreshDatabase
only rolls back.https://github.com/laravel/framework/blob/5.5/src/Illuminate/Foundation/Testing/RefreshDatabase.php https://github.com/laravel/framework/blob/5.5/src/Illuminate/Foundation/Testing/DatabaseTransactions.php
I can’t test it at this moment. But I’m pretty this is the problem. The solution by the issue starter fixes it, and that just adds the missing disconnect.
@jycr753 There is always possibility to use sqlite driver with
:memory:
database, which is perfect for testing.But remember to enable constrains checks https://sqlite.org/foreignkeys.html
I had a similar problem not too long ago in Lumen, and solved it with:
I’m currently experiencing this problem on 5.5.24.
Adding this to my config solved it:
We are using Doctrine via
Connection::getDoctrineSchemaManager()
, and it seems like the Doctrine connection (and hence the PDO) doesn’t get cleaned up at the end of each of our unit tests, despite going\DB::purge(...)
. If we do the following instead, it solves this issue for us:Is this perhaps the issue you’re facing as well?
And is it intentional to have to clean up a Doctrine connection like this?
(PHP 7.1, laravel/framework 5.4.27, doctrine/dbal 2.5.12, Postgres 9.5.7)