Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If a query result has multiple rows, timeouts aren't always triggered properly #1501

Open
karlra opened this issue Jul 27, 2024 · 0 comments

Comments

@karlra
Copy link

karlra commented Jul 27, 2024

Software versions
MySqlConnector version: 2.3.7
Server type (MySQL, MariaDB, Aurora, etc.) and version: Mysql 8.0
.NET version:
6.0

Describe the bug
I can't tell if this is a bug or not but it feels like one. If you execute a query that has multiple rows where one row seems to be "ready" already, the .CommandTimeout property doesn't work as you would expect. CancellationToken query cancellation displays the same behaviour.

The query below is attempting to select 3 rows, with the values {1,0,2}. A timeout of 10 seconds is specified, but if you don't Read() the row that would've triggered the timeout on the command there is no exception being generated and it appears as if the query worked as expected.

The server thread is still cancelled after 1 second as expected, but there is no timeout exception triggered.

Code sample

            MySqlConnection conn = new MySqlConnection("...");
            await conn.OpenAsync();
            using(var cmd = conn.CreateCommand())
            {
                cmd.CommandText = "select 1 union all select sleep(10) union all select 2";
                cmd.CommandTimeout = 1;
                using(var reader = await cmd.ExecuteReaderAsync())
                {
                    await reader.ReadAsync();
                    var i = reader.GetInt32(0);
                    Console.WriteLine(i); //Prints 1

                    /* Uncomment to trigger the timeout exception
                    await reader.ReadAsync();
                    i = reader.GetInt32(0);
                    Console.WriteLine(i);
                    */
                }

            }

Inserts are even weirder:

            
            MySqlConnection conn = new MySqlConnection("...");
            await conn.OpenAsync();
            using(var cmd = conn.CreateCommand())
            {
                cmd.CommandText = @"
                    drop table if exists test;
                    create table test
                        ( `a` int NOT NULL, PRIMARY KEY (`a`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
                ";
                await cmd.ExecuteNonQueryAsync();

                cmd.CommandText = "insert into test set a = 1; select sleep(10); insert into test set a = 2;";
                cmd.CommandTimeout = 1;
                using(var reader = await cmd.ExecuteReaderAsync())
                {
                    await reader.ReadAsync();
                    var i = reader.GetInt32(0);
                    Console.WriteLine(i);
                }

            }

The second example triggers no exception, and if you check the database afterwards it contains two rows with values 1,2.

Expected behavior
We would expect an exception to be triggered after 1 seconds no matter what the server thread was doing, no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant