Closed gwy15 closed 2 years ago
Update: concurrency is not a must-have to reproduce this problem (though will be more effient), I can reproduce with this simple code:
let pool = db::connect(&url).await?;
let mut conn = pool.get().await?;
for i in 0..16382 + 10 {
let new = models::NewUser {
name: &format!("name-{}", i),
email: &format!("email-{}", i),
};
models::User::insert(new, &mut conn).await?;
}
Thanks for writing this bug report. I cannot reproduce this behavior using mariadb 10.5.16 on linux, even with a much lower max_prepared_stmt_count
. Can you add information about your environment? Especially important are the following information:
max_prepared_stmt_count
to some higher/lower value changes something.I used docker version of mysql, which is mysql:5.7
. the max_prepared_stmt_count
should be default value 16382 (https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_prepared_stmt_count).
Changing the value does not affect anything, but commenting this line does eliminate the error
https://github.com/weiznich/diesel_async/blob/main/src/mysql/mod.rs#L67
I can reproduce on mariadb on Windows via Docker (mariadb:latest)
version: '3.9'
services:
mariadb:
image: mariadb:latest
ports:
- "3306:3306"
volumes:
- ./maria-data:/var/lib/mysql
environment:
MARIADB_ROOT_PASSWORD: NNe47zF3JRhr6Ykb
MARIADB_DATABASE: db
I can make a PR to fix this real quick by applying Queryable::close
to dropping last_stmt, but I really appreciate if some questions can be explained to me:
AsyncMysqlConnection::last_stmt
purely a workround so that the callback fn signature still gets a reference instead of a owned stmt? I guess something like a MaybeOwned
is more intuitive from my personal perspective.Why are we using our own statement caching mechanism instead of mysql_async's caching mechanism?
Because mysql_async
statement caching mechanism is less powerful than what diesel offers. mysql_async
basically caches any statement by using the sql string as cache key entry. Diesel on the other hand "knows" at compile time whether:
The first point let's us decide whether to cache or not to cache, while the second point allows us in some cases to just skip query building at all and use a compile time "id" to address the statement cache and receive an already prepared statement from there. Checkout this documentation for details. (The implementation in diesel_async
closely mirrors the main diesel implementation and uses essentially the same query building infrastructure)
Is the AsyncMysqlConnection::last_stmt purely a workround so that the callback fn signature still gets a reference instead of a owned stmt? I guess something like a MaybeOwned is more intuitive from my personal perspective.
Yes that is purely a workaround to get things working. With the assumption that Statement::drop
automatically drops the deallocates the statement as well, this seems like the "easy" solution. As demonstrated by this bug report that was wrong.
Statement
, but I do really not see any good solution there yet.
diesel-async + AsyncMysqlConnection gives error after executing more than 16382 inserts, while diesel does not
outdated reprodicible example
Hi. I'm setting up a really simple [template repo](https://github.com/gwy15/diesel-async-example) for my own use and I tried to [insert-select-delete](https://github.com/gwy15/diesel-async-example/blob/main/tests/insert_and_validate.rs#L51) concurrently.Specifically, I used 100 threads/futures, each insert-select-delete 200 times. The thread pool was set max connection count to 30.diesel-async gives the error, whilst disel(sync) does not and can finish as expected. ``` Can't create more than max_prepared_stmt_count statements (current value: 16382) ```On my local machine they both reached about ~2k QPS. The concurrent connections was 30.reproducible repo (with corresponding failing CI): https://github.com/gwy15/diesel-async-exampleSetup
Versions
Feature Flags
What are you trying to accomplish?
Since diesel + multithread does not have a problem, I expect diesel-async to have the same ability.
What is the actual output?
Can't create more than max_prepared_stmt_count statements
Are you seeing any additional errors?
No
Steps to reproduce
migration
main.rs
cargo.toml
outdated
Please see my repo https://github.com/gwy15/diesel-async-example, and the CI workflow https://github.com/gwy15/diesel-async-example/actions/runs/3175713190 is exactly what I had on my local machine. to run locally, please ```bash git clone https://github.com/gwy15/diesel-async-example cd diesel-async-example docker-compose up -d diesel migration run cargo t --no-default-features --features async ```Checklist