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.inetc.).“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