When working with databases, š userver provides the ability to create a transaction in code and execute database queries within it. From creation to commit/rollback, a transaction holds one of the database connections entirely. If a heavy operation is called during the transactionās lifetime (e.g., an HTTP request), then in case of an incident (e.g., the service being called via HTTP goes down), the execution time of that operation will increase. Consequently, the transactionās lifetime will also increase while the connection is hold, which may cause the entire database to fail.
Consequently there is a built-in mechanism for long transactions detection. See also utils::trx_tracker.
To detect long operations within transactions, we insert a check for active transactions into every heavy operation in userver. When triggered, this check writes a log and a metric.
The check is inserted into:
Transactions from the following databases are monitored:
The check works in testsuite tests but is disabled in gtest and gbenchmark.
Logs:
When the check is triggered, the service will spam WARN logs with the following text: Long call while having active transactions. The meta.location field displays the name of the method that calls the endpoint where the check was triggered.
Metrics:
Metric: engine.heavy-operations-in-transactions is incremented in case of heavy operation in transaction.
Move the heavy request out from the transaction.
If the bahavior is understood and it is fine to have a long transaction in that particular case, the check could be disabled for a scope via utils::trx_tracker::CheckDisabler :
To disable the check for the whole service use the enable_trx_tracker static configuration option of components::ManagerControllerComponent. Note that this is not recommended.