-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] Hyperf\DbConnection\Db blocks other coroutines from getting a database pool connection #6611
Comments
You can use wait() function to solve this.
|
你的运行环境不在 |
@limingxinleo wow thanks brilliant idea I never thought about performing each database task inside a coroutine 👍👌 I was not aware of that @lazychanger yes it is running in coroutine environment, |
This feature may be added in v3.2 |
Amazing!
I guess it just needs to get the |
There is another problem though - if we call this new I tried to solve this: // 1. Get the connection object out of the coroutine context
$connectionName = 'default';
$contextKey = "database.connection.$connectionName"; // see ConnectionResolver.php getContextKey()
$db = \Hyperf\Context\Context::get($contextKey);
// 2. Send ANOTHER coroutine to release that connection, so our coroutine can continue running
\Hyperf\Engine\Coroutine::create(fn($db) => $db->release(), $db);
// Now our coroutine can continue executing and not suspend / wait for connection pool channel!
// 3. In our coroutine delete / set null the $db variable
// this is to satisfy ConnectionResolver.php connection() condition if(Context::has($id))
$db = null;
unset($db);
\Hyperf\Context\Context::set($contextKey, null);
\Hyperf\Context\Context::destroy($contextKey);
// If we call Db:: again in our coroutine it should successfully obtain another connection from the pool
// ... right?
But then I start getting this error - maybe I'm doing something wrong and there is a solution to do it right?
|
Issue:
Hyperf\DbConnection\Db
occupies pool connections the entire lifetime of the coroutine, blocking other coroutines from getting a DB connection.For example if a coroutine performs work such as: 1) query the database 2) do some HTTP requests to APIs etc. 3) update the database or other tasks etc. then
Hyperf\DbConnection\Db
will get a pool connection in step 1 and keep it reserved and does not release it back to the pool even if step 2 HTTP/API requests take time, other coroutines waiting to useDb::
cannot get from the pool until this coroutine ends (whendefer()
is called to release the DB connection back to the pool)See hyperf/db-connection/src/ConnectionResolver.php where
$pool->get()
anddefer()
and$connection->release();
is calledSteps To Reproduce:
Create many coroutines to perform database tasks using
Db::
and other tasks which take some time like HTTP requests etc.Early / first coroutines will get database pool connections right away and proceed with their tasks
But later coroutines will wait in the connection pool channel until those db connections are released, even if the Early coroutines take 10 or 15 or 30sec+ to perform their HTTP tasks, later coroutines cannot even perform their 1st database task until the early coroutines finish and return.
Solution?
Possibility to release the pool connection on-demand earlier in the coroutine before performing time consuming work like HTTP requests or other such tasks?
The text was updated successfully, but these errors were encountered: