MySQL Prepared Statement Count Error
Ever encountered this error?
SequelizeDatabaseError: Can't create more than max_prepared_stmt_count statements (current value: 16382)
I have. I came across it after deploying an update to one of our Node.js apps, specifically a worker with bulk data creation and updates. So I'm writing this as a note for my future self.
Here's the gist of it:
Some Sequelize operations create Prepared Statements (e.g. operations with
Op.in
etc.)."A prepared statement is a feature used to execute the same (or similar) SQL statements repeatedly with high efficiency." - W3Schools
These prepared statements are reused over time, with variables replaced (if done correctly) so they are cached by the MySQL server.
There's a limit to the number of prepared statements that can be stored in the cache (16382 by default).
When this limit is exceeded, all connections to the Database fail and your app will become unresponsive.
Unfortunately, as I used Sequelize and the default number of cached prepared statements is 16000
(per connection!!!), my app crashed - all processes couldn't connect to the Database and I was shown the error above.
You can prevent this by setting the maxPreparedStatements
value of your Sequelize config's dialectOptions
property to a value where
max_prepared_stmt_count >= number of connections * value
e.g. 100, in the SequelizeOptions shown below
import { Options } from 'sequelize/types';
const config: Options = {
username: process.env.DB_USER!,
password: process.env.DB_PASSWORD!,
database: process.env.DB_DATABASE!,
host: process.env.DB_HOST!,
port: +process.env.DB_PORT! || 3306,
dialect: 'mysql',
logging: false,
pool: {
max: 20,
min: 0,
acquire: 60000,
idle: 10000,
},
dialectOptions: {
bigNumberStrings: true,
/* here */
maxPreparedStatements: 100,
},
}
Assuming we have 5 Node.js processes using the config above, we'll have
totalCachedStatements = 5 * 100 * 20
totalCachedStatements = 10000
and since it's below 16382
, it's gonna be some smooth sailing for our application.
PS: Another option to solve this was to increase the value of the max_prepared_stmt_count
on the MySQL server but I didn't want to do that as you might not have access to a privileged user to run the commands.
For more info, you can read