-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Bug Description
Not really sure what exactly the bug is but i am seeing strange behavior that makes it look like sql statements are not executed in the correct order. I have a reproduction here ( https://github.com/pythoneer/sqlx_test ) , but it is not really minimal. It uses axum and some strange wrk stuff to trigger it, because that is where i originally encountered that behavior, not sure if it could be further reduced or if it has something to do with how axum operates specifically.
I am just trying to do this in a handler
async fn test(State(pool): State<PgPool>) -> Result<String, (StatusCode, String)> {
sleep(Duration::from_millis(2)).await;
let mut transaction = pool.begin().await.map_err(internal_error)?;
// -----------------------8<--------- this is optional ---------------->8----------
transaction
.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;")
.await
.map_err(|err| panic!("Failed to set transaction isolation level: {:#?}", err))?;
let data: String = sqlx::query_scalar("select 'hello world from pg'")
.fetch_one(&pool)
.await
.map_err(internal_error)?;
// -----------------------8<--------- this is optional ---------------->8----------
transaction.commit().await.map_err(internal_error)?;
Ok(data)
}The SET TRANSACTION... and the select 'hello .. can also be removed it will already trigger the problem with just
let mut transaction = pool.begin().await.map_err(internal_error)?;
let transaction.commit().await.map_err(internal_error)?;but it helps demonstrating the problem.
by running
DATABASE_URL="<your_url>" cargo run --bin binary2
and
./parallel_run.sh
to hit the endpoint we can sporadically see
2023-10-07T20:07:04.706970Z WARN sqlx::postgres::notice: there is already a transaction in progress
2023-10-07T20:07:08.272585Z WARN sqlx::postgres::notice: there is no transaction in progress
which i can't really explain. The only way i can think of is if the statements send to the database are not in order? Normally we would see BEGIN; COMMIT; pairs send parallel in each connection, right? But the warnings make me assume that sometime BEGIN; BEGIN; COMMIT; or BEGIN; COMMIT; COMMIT; happens.
With the additional SET TRANSACTION ... and select 'hello .. we can also see panics that i create with
.map_err(|err| panic!("Failed to set transaction isolation level: {:#?}", err))?;that shows
code: "25001",
message: "SET TRANSACTION ISOLATION LEVEL must be called before any query",
and the same problem here, i can only explain this (just playing around in psql) if the select 'hello .. is executed before SET TRANSACTION ....
sqlx.mp4
Also the values (like the sleep and all the wrk parameters and connection pool size) might depend on the specific machine idk, i tuned them to be working the best on my system. I think this can change from system to system. I think it worked the best when the endpoint delivered around 2500 req/s. The reason why i am doing the "funny" stuff in parallel_run.sh is because i noticed that this is somehow triggered specifically in the beginning or the end of a wrk run, not really sure why and what is happening in detail. Maybe wrk "just" kills connection in the middle and axum reacts strange to killed connections while a handler is running idk. But i would say regardless of what axum is doing i don't expect any of the observed things to happen. You can trigger this without parallel_run.sh but you might need to wait and potentially start and stop the wrk command manually fast consecutively. That is basically what parallel_run.sh is doing.
Minimal Reproduction
https://github.com/pythoneer/sqlx_test
needs wrk installed for parallel_run.sh.
DATABASE_URL="<your_url>" cargo run --bin binary2
and
./parallel_run.sh
Info
- SQLx version: 0.7.2
- SQLx features enabled:
"postgres",
"runtime-tokio-rustls",
"macros", "migrate",
"chrono", "json", "uuid", - Database server and version: PostgreSQL 15.4 on x86_64-pc-linux-musl, compiled by gcc (Alpine 12.2.1_git20220924-r10) 12.2.1 20220924, 64-bit
- Operating system: arch linux (x86_64 Linux 6.5.5-arch1-1)
rustc --version: rustc 1.72.0 (5680fa18f 2023-08-23)