Skip to content

Commit cb3991e

Browse files
authored
Merge pull request #10428 from ziggie1984/fix-sql-pool-exhaustion
graphdb: fix potential sql tx exhaustion
2 parents bc670fa + f289e49 commit cb3991e

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

docs/release-notes/release-notes-0.20.1.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
in the mission control store. Now we skip over potential errors and also
4343
delete them from the store.
4444

45+
* [Fix potential sql tx exhaustion
46+
issue](https://github.com/lightningnetwork/lnd/pull/10428) in LND which might
47+
happen when running postgres with a limited number of connections configured.
48+
4549
# New Features
4650

4751
## Functional Enhancements

graph/db/kv_store.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,13 @@ func (c *KVStore) fetchNextChanUpdateBatch(
21082108
batch []ChannelEdge
21092109
hasMore bool
21102110
)
2111+
2112+
// Acquire read lock before starting transaction to ensure
2113+
// consistent lock ordering (cacheMu -> DB) and prevent
2114+
// deadlock with write operations.
2115+
c.cacheMu.RLock()
2116+
defer c.cacheMu.RUnlock()
2117+
21112118
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
21122119
edges := tx.ReadBucket(edgeBucket)
21132120
if edges == nil {
@@ -2187,9 +2194,7 @@ func (c *KVStore) fetchNextChanUpdateBatch(
21872194
continue
21882195
}
21892196

2190-
// Before we read the edge info, we'll see if this
2191-
// element is already in the cache or not.
2192-
c.cacheMu.RLock()
2197+
// Check cache (we already hold shared read lock).
21932198
if channel, ok := c.chanCache.get(chanIDInt); ok {
21942199
state.edgesSeen[chanIDInt] = struct{}{}
21952200

@@ -2200,11 +2205,8 @@ func (c *KVStore) fetchNextChanUpdateBatch(
22002205

22012206
indexKey, _ = updateCursor.Next()
22022207

2203-
c.cacheMu.RUnlock()
2204-
22052208
continue
22062209
}
2207-
c.cacheMu.RUnlock()
22082210

22092211
// The edge wasn't in the cache, so we'll fetch it along
22102212
// w/ the edge policies and nodes.

graph/db/sql_store.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,11 @@ func (s *SQLStore) ChanUpdatesInHorizon(startTime, endTime time.Time,
11271127
for hasMore {
11281128
var batch []ChannelEdge
11291129

1130+
// Acquire read lock before starting transaction to
1131+
// ensure consistent lock ordering (cacheMu -> DB) and
1132+
// prevent deadlock with write operations.
1133+
s.cacheMu.RLock()
1134+
11301135
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(),
11311136
func(db SQLQueries) error {
11321137
//nolint:ll
@@ -1179,11 +1184,11 @@ func (s *SQLStore) ChanUpdatesInHorizon(startTime, endTime time.Time,
11791184
continue
11801185
}
11811186

1182-
s.cacheMu.RLock()
1187+
// Check cache (we already hold
1188+
// shared read lock).
11831189
channel, ok := s.chanCache.get(
11841190
chanIDInt,
11851191
)
1186-
s.cacheMu.RUnlock()
11871192
if ok {
11881193
hits++
11891194
total++
@@ -1217,6 +1222,9 @@ func (s *SQLStore) ChanUpdatesInHorizon(startTime, endTime time.Time,
12171222
)
12181223
})
12191224

1225+
// Release read lock after transaction completes.
1226+
s.cacheMu.RUnlock()
1227+
12201228
if err != nil {
12211229
log.Errorf("ChanUpdatesInHorizon "+
12221230
"batch error: %v", err)

0 commit comments

Comments
 (0)