You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(spanner): enable long running transaction clean up (#8969)
* feat(spanner): enable long running txn clean up with default as WARN
* feat(spanner): remove mutex that does not exist in main branch
* feat(spanner): update tests
* feat(spanner): comment update
A `Client` object of the Client Library has a limit on the number of maximum sessions. For example the
38
+
default value of `MaxOpened`, which is the maximum number of sessions allowed by the session pool in the
39
+
Golang Client Library, is 400. You can configure these values at the time of
40
+
creating a `Client` by passing custom `SessionPoolConfig` as part of `ClientConfig`. When all the sessions are checked
41
+
out of the session pool, every new transaction has to wait until a session is returned to the pool.
42
+
If a session is never returned to the pool (hence causing a session leak), the transactions will have to wait
43
+
indefinitely and your application will be blocked.
44
+
45
+
#### Common Root Causes
46
+
The most common reason for session leaks in the Golang client library are:
47
+
1. Not stopping a `RowIterator` that is returned by `Query`, `Read` and other methods. Always use `RowIterator.Stop()` to ensure that the `RowIterator` is always closed.
48
+
2. Not closing a `ReadOnlyTransaction` when you no longer need it. Always call `ReadOnlyTransaction.Close()` after use, to ensure that the `ReadOnlyTransaction` is always closed.
49
+
50
+
As shown in the example below, the `txn.Close()` statement releases the session after it is complete.
51
+
If you fail to call `txn.Close()`, the session is not released back to the pool. The recommended way is to use `defer` as shown below.
// Example Log message for when transaction is recycled
114
+
// session <session-info> checked out of pool at <session-checkout-time> is long running and will be removed due to possible session leak for goroutine
if (p.actionOnInactiveTransaction==Warn||p.actionOnInactiveTransaction==WarnAndClose) &&!sh.isSessionLeakLogged {
730
-
ifp.actionOnInactiveTransaction==Warn {
729
+
if (p.ActionOnInactiveTransaction==Warn||p.ActionOnInactiveTransaction==WarnAndClose) &&!sh.isSessionLeakLogged {
730
+
ifp.ActionOnInactiveTransaction==Warn {
731
731
ifsh.stack!=nil {
732
732
logf(p.sc.logger, "session %s checked out of pool at %s is long running due to possible session leak for goroutine: \n%s", sh.session.getID(), sh.checkoutTime.Format(time.RFC3339), sh.stack)
733
733
} else {
734
734
logf(p.sc.logger, "session %s checked out of pool at %s is long running due to possible session leak for goroutine: \nEnable SessionPoolConfig.TrackSessionHandles to get stack trace associated with the session", sh.session.getID(), sh.checkoutTime.Format(time.RFC3339))
logf(p.sc.logger, "session %s checked out of pool at %s is long running and will be removed due to possible session leak for goroutine: \n%s", sh.session.getID(), sh.checkoutTime.Format(time.RFC3339), sh.stack)
740
740
} else {
741
741
logf(p.sc.logger, "session %s checked out of pool at %s is long running and will be removed due to possible session leak for goroutine: \nEnable SessionPoolConfig.TrackSessionHandles to get stack trace associated with the session", sh.session.getID(), sh.checkoutTime.Format(time.RFC3339))
0 commit comments