feat: mysql add prepared_stmt_cache_capacity (#6639)

* feat: your clear and concise commit message

Signed-off-by: sunheyi <1061867552@qq.com>

* fix error

Signed-off-by: sunheyi <1061867552@qq.com>

* add param

Signed-off-by: sunheyi <1061867552@qq.com>

* fix

Signed-off-by: sunheyi <1061867552@qq.com>

* fix doc error

Signed-off-by: sunheyi <1061867552@qq.com>

---------

Signed-off-by: sunheyi <1061867552@qq.com>
This commit is contained in:
sunheyi
2025-08-14 16:19:10 +08:00
committed by GitHub
parent 4d97754cb4
commit d03f85287e
11 changed files with 47 additions and 4 deletions

View File

@@ -41,6 +41,7 @@
| `mysql.addr` | String | `127.0.0.1:4002` | The addr to bind the MySQL server. |
| `mysql.runtime_size` | Integer | `2` | The number of server worker threads. |
| `mysql.keep_alive` | String | `0s` | Server-side keep-alive time.<br/>Set to 0 (default) to disable. |
| `mysql.prepared_stmt_cache_size` | Integer | `10000` | Maximum entries in the MySQL prepared statement cache; default is 10,000. |
| `mysql.tls` | -- | -- | -- |
| `mysql.tls.mode` | String | `disable` | TLS mode, refer to https://www.postgresql.org/docs/current/libpq-ssl.html<br/>- `disable` (default value)<br/>- `prefer`<br/>- `require`<br/>- `verify-ca`<br/>- `verify-full` |
| `mysql.tls.cert_path` | String | Unset | Certificate file path. |
@@ -248,6 +249,7 @@
| `mysql.addr` | String | `127.0.0.1:4002` | The addr to bind the MySQL server. |
| `mysql.runtime_size` | Integer | `2` | The number of server worker threads. |
| `mysql.keep_alive` | String | `0s` | Server-side keep-alive time.<br/>Set to 0 (default) to disable. |
| `mysql.prepared_stmt_cache_size` | Integer | `10000` | Maximum entries in the MySQL prepared statement cache; default is 10,000. |
| `mysql.tls` | -- | -- | -- |
| `mysql.tls.mode` | String | `disable` | TLS mode, refer to https://www.postgresql.org/docs/current/libpq-ssl.html<br/>- `disable` (default value)<br/>- `prefer`<br/>- `require`<br/>- `verify-ca`<br/>- `verify-full` |
| `mysql.tls.cert_path` | String | Unset | Certificate file path. |

View File

@@ -90,6 +90,8 @@ runtime_size = 2
## Server-side keep-alive time.
## Set to 0 (default) to disable.
keep_alive = "0s"
## Maximum entries in the MySQL prepared statement cache; default is 10,000.
prepared_stmt_cache_size = 10000
# MySQL server TLS options.
[mysql.tls]

View File

@@ -85,7 +85,8 @@ runtime_size = 2
## Server-side keep-alive time.
## Set to 0 (default) to disable.
keep_alive = "0s"
## Maximum entries in the MySQL prepared statement cache; default is 10,000.
prepared_stmt_cache_size= 10000
# MySQL server TLS options.
[mysql.tls]

View File

@@ -230,6 +230,7 @@ where
tls_server_config,
opts.keep_alive.as_secs(),
opts.reject_no_database.unwrap_or(false),
opts.prepared_stmt_cache_size,
)),
Some(instance.process_manager().clone()),
);

View File

@@ -29,6 +29,7 @@ pub struct MysqlOptions {
#[serde(default = "Default::default")]
#[serde(with = "humantime_serde")]
pub keep_alive: std::time::Duration,
pub prepared_stmt_cache_size: usize,
}
impl Default for MysqlOptions {
@@ -40,6 +41,7 @@ impl Default for MysqlOptions {
tls: TlsOption::default(),
reject_no_database: None,
keep_alive: std::time::Duration::from_secs(0),
prepared_stmt_cache_size: 10000,
}
}
}

View File

@@ -83,6 +83,7 @@ pub struct MysqlInstanceShim {
prepared_stmts: Arc<RwLock<HashMap<String, SqlPlan>>>,
prepared_stmts_counter: AtomicU32,
process_id: u32,
prepared_stmt_cache_size: usize,
}
impl MysqlInstanceShim {
@@ -91,6 +92,7 @@ impl MysqlInstanceShim {
user_provider: Option<UserProviderRef>,
client_addr: SocketAddr,
process_id: u32,
prepared_stmt_cache_size: usize,
) -> MysqlInstanceShim {
// init a random salt
let mut bs = vec![0u8; 20];
@@ -118,6 +120,7 @@ impl MysqlInstanceShim {
prepared_stmts: Default::default(),
prepared_stmts_counter: AtomicU32::new(1),
process_id,
prepared_stmt_cache_size,
}
}
@@ -159,9 +162,24 @@ impl MysqlInstanceShim {
}
/// Save query and logical plan with a given statement key
fn save_plan(&self, plan: SqlPlan, stmt_key: String) {
fn save_plan(&self, plan: SqlPlan, stmt_key: String) -> Result<()> {
let mut prepared_stmts = self.prepared_stmts.write();
let max_capacity = self.prepared_stmt_cache_size;
let is_update = prepared_stmts.contains_key(&stmt_key);
if !is_update && prepared_stmts.len() >= max_capacity {
return error::InternalSnafu {
err_msg: format!(
"Prepared statement cache is full, max capacity: {}",
max_capacity
),
}
.fail();
}
let _ = prepared_stmts.insert(stmt_key, plan);
Ok(())
}
/// Retrieve the query and logical plan by a given statement key
@@ -237,7 +255,11 @@ impl MysqlInstanceShim {
schema: None,
},
stmt_key,
);
)
.map_err(|e| {
error!(e; "Failed to save prepared statement");
e
})?;
} else {
self.save_plan(
SqlPlan {
@@ -247,7 +269,11 @@ impl MysqlInstanceShim {
schema,
},
stmt_key,
);
)
.map_err(|e| {
error!(e; "Failed to save prepared statement");
e
})?;
}
Ok((params, columns))

View File

@@ -77,6 +77,8 @@ pub struct MysqlSpawnConfig {
keep_alive_secs: u64,
// other shim config
reject_no_database: bool,
// prepared statement cache capacity
prepared_stmt_cache_size: usize,
}
impl MysqlSpawnConfig {
@@ -85,12 +87,14 @@ impl MysqlSpawnConfig {
tls: Arc<ReloadableTlsServerConfig>,
keep_alive_secs: u64,
reject_no_database: bool,
prepared_stmt_cache_size: usize,
) -> MysqlSpawnConfig {
MysqlSpawnConfig {
force_tls,
tls,
keep_alive_secs,
reject_no_database,
prepared_stmt_cache_size,
}
}
@@ -201,6 +205,7 @@ impl MysqlServer {
spawn_ref.user_provider(),
stream.peer_addr()?,
process_id,
spawn_config.prepared_stmt_cache_size,
);
let (mut r, w) = stream.into_split();
let mut w = BufWriter::with_capacity(DEFAULT_RESULT_SET_WRITE_BUFFER_SIZE, w);

View File

@@ -72,6 +72,7 @@ fn create_mysql_server(table: TableRef, opts: MysqlOpts<'_>) -> Result<Box<dyn S
tls_server_config,
0,
opts.reject_no_database,
10000,
)),
None,
))

View File

@@ -645,6 +645,7 @@ pub async fn setup_mysql_server_with_user_provider(
),
0,
opts.reject_no_database.unwrap_or(false),
opts.prepared_stmt_cache_size,
)),
None,
);

View File

@@ -1249,6 +1249,7 @@ enable = true
addr = "127.0.0.1:4002"
runtime_size = 2
keep_alive = "0s"
prepared_stmt_cache_size = 10000
[mysql.tls]
mode = "disable"

View File

@@ -27,6 +27,7 @@ runtime_size = 8
enable = true
addr = "{mysql_addr}"
runtime_size = 2
prepared_stmt_cache_size= 10000
[mysql.tls]
mode = "disable"