Drop prepared statement cache#5094
Conversation
There was a problem hiding this comment.
Pull request overview
This PR removes the prepared statement caching mechanism from stellar-core's database layer. The motivation is that with the transition to BucketListDB and minimal SQL usage (30-50 queries/second on pubnet), the complexity of maintaining prepared statement caches outweighs the benefits. The lack of consistent cache clearing discipline (as noted in issue #1591) and recent bugs like #5093 further support this simplification.
Key changes:
- Complete removal of prepared statement cache infrastructure from Database class
- Simplified
getPreparedStatementto create fresh statement handles on each call - Removed all
clearPreparedStatementCachecalls throughout the codebase - Updated exception safety documentation in LedgerTxnImpl.h to remove stale cache references
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/database/Database.h | Removed PreparedStatementCache type, mCaches map, mStatementsSize metric, mStatementsMutex, and clearPreparedStatementCache declaration; updated getPreparedStatement documentation |
| src/database/Database.cpp | Simplified getPreparedStatement to create fresh statements without caching; removed clearPreparedStatementCache implementation and all its invocations; removed mStatementsSize metric initialization |
| src/ledger/LedgerTxnImpl.h | Removed prepared statement cache references from exception safety documentation for all affected methods |
| src/ledger/LedgerTxn.cpp | Removed clearPreparedStatementCache calls from commitChild and rollbackChild |
| src/main/ApplicationImpl.cpp | Removed clearPreparedStatementCache calls from maybeRebuildLedger |
| src/ledger/LedgerManagerImpl.cpp | Removed clearPreparedStatementCache call from advanceLedgerStateAndPublish |
| src/catchup/CatchupWork.cpp | Removed clearPreparedStatementCache call from runCatchupStep |
| src/test/FuzzerImpl.cpp | Removed clearPreparedStatementCache call from resetTxInternalState |
|
I'm pretty sure the high impact here would be path payment in classic, so you need to look at ledger ranges with high volatility |
we agreed with the team that we'll merge this to get CI going (including full catchup that has ranges you're talking about), while doing perf evaluation in parallel. Then, if needed, we can cache queries for relevant subsystems. It's not certain classic paths are actually high impact since the code is using ltx and we're doing bulk upserts, not individual updates. |
|
(late to the party -- sorry was out at doctor -- but I'm fine with this; prepared statements made sense when we were hitting the db thousands of times per second and when it was postgresql; but once we had the ltx that stopped being a real issue, and moving to sqlite-only will make it even less of an issue. I'd be very surprised if this change has any impact perf-wise.) |
|
regarding perf of this change:
I ran catchup on [53620637-53621000] which was flagged before for slow ledgers crossing hundreds of thousands of offers. Note that before every run OS caches were flushed. Results look basically identical on SQLite. On Postgres, there's a slight degradation (13%). SQLite without prepared statements - 96.41s Postgres without prepared statements - 78.87s Given that apply is in the background anyway, and the change isn't particularly drastic in "bad" regions, it seems fine to me to proceed, although if anyone feels strongly I suppose we could bring back caching for Postgres (I still don't believe the complexity is worth it given that prepared statements have been a headache for years at this point). |
|
I'm fine with this. With luck 2026 will be the year we remove postgres support anyway. |
With recent bugs like #5093 I realized prepared statements at this point cause more harm than good. We've moved to BucketListDB as a backend a while ago, removed SQL from publishing completely, and now the use of SQL in the codebase is minimal. In addition, for the remaining SQL bits like offers, we do batch load/inserts. The lack of consistent clearing discipline as described in #1591 makes this even harder to think about. On pubnet infra, it looks like we're executing 30-50 queries per second, which is fairly low. This PR removes prepared statement caching completely. I'm currently doing a perf evaluation of this change, but we can probably merge it and if needed, bring back caching for subsystems that could benefit from it.