feat(AR): Force Rails to specify column list #3640
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Context
Some
ActiveRecord::PreparedStatementCacheExpired
started popping up recently, always during deploy.TL;DR
The DB uses some cache and when a table is modified (adding/removing column) it's invalidate the cache. If this happens in the middle of a transaction, it breaks!
The best solution is to force Rails to list all columns in select queries instead of using
SELECT *
. The cache will continue to be valid because the "result type" wasn't changed.Description
This is only an issue when the migration happened during an open transaction. Our pods are running during the migration so this happens sometimes. Then, all pods are "restarted" (rolling roll out).
Solution
The only known way to force Rails to list all columns in a select query is to ignore columns. The feature is used to stop using a column before it's removed from the table.
To ensure all models have something in
self.ignored_columns
we add a fake name to the parentApplicationRecord
. The column doesn't have to exist.https://flexport.engineering/avoiding-activerecord-preparedstatementcacheexpired-errors-4499a4f961cf
rails/rails#22170
Before / After
It's a little annoying because the query is getting very big and only a little bit is meaningful but it's a small price to pay.