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

Arithmetic Overflow in ExecuteNonQuery #966

Closed
akamor opened this issue Apr 10, 2021 · 9 comments
Closed

Arithmetic Overflow in ExecuteNonQuery #966

akamor opened this issue Apr 10, 2021 · 9 comments

Comments

@akamor
Copy link
Contributor

akamor commented Apr 10, 2021

Running a series of ALTER TABLE statements and get this exception. The queries themselves are simply dropping the AUTO_INCREMENT property on a bunch of tables, e.g .ALTER TABLE

MODIFY COLUMN bigint(20) NOT NULL;

Not sure how we could get an overflow but looking at the code a bit it might be happening during establishing a connection?

One last thing to note is that for some reason one of these queries caused a hang that lasted ~13 hours. The command timeout is set to 0, however, and normally when we do so timeout exceptions the error message is quite clear.

MySqlConnector.MySqlException (0x80004005): Failed to read the result set. 
 ---> System.OverflowException: Arithmetic operation resulted in an overflow. 
   at MySqlConnector.Protocol.Payloads.OkPayload.Create(ReadOnlySpan`1 span, Boolean deprecateEof, Boolean clientSessionTrack) in /_/src/MySqlConnector/Protocol/Payloads/OkPayload.cs:line 31 
   at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) 
   at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 119 
   at MySqlConnector.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 444 
   at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 60 
   at MySqlConnector.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 266 
   at MySqlConnector.MySqlCommand.ExecuteNonQuery() in /_/src/MySqlConnecto
@bgrainger
Copy link
Member

The line numbers don't match up exactly, but seems like it could be this line:

var affectedRowCount = checked((int) reader.ReadLengthEncodedInteger());

@bgrainger
Copy link
Member

Do you have more than 2 billion rows in this table?

@akamor
Copy link
Contributor Author

akamor commented Apr 10, 2021

I was thinking along those lines as well because we've seen issues in the past around row count, however, affectedRowCount seems to remain at 0 when running ALTER TABLE .... MODIFY COLUMN queries? I haven't tested it on a 2B row table, however, I did test it with some tables with a few hundren to a few million rows and that value remains 0.

With that being said, the database where the issue is occuring does have 2B row tables.

@akamor
Copy link
Contributor Author

akamor commented Apr 10, 2021

I'm generating a 2B row table now, I'll have results soon.

@bgrainger
Copy link
Member

MySQL can return a 64-bit integer for the number of rows affected; this was prematurely being truncated to a 32-bit signed integer.

@akamor
Copy link
Contributor Author

akamor commented Apr 11, 2021

I haven't been able to get a table with 2B+ rows yet but I'll have it in the AM. Did you happen to test your fix against a sufficiently large table?

The only reason I ask is that when I run the query on my side (ALTER TABLE .... MODIFY COLUMN ...) the affectedRowCount, e.g.,

var affectedRowCount = reader.ReadLengthEncodedInteger();

is always 0 so I am not sure how the overflow would occur there.

@bgrainger
Copy link
Member

I haven't tested it on a large table, but it just seems reasonable that the code shouldn't unnecessarily bounds-check the value returned from the server (when there's no immediate need to coerce it to 32 bits).

@bgrainger
Copy link
Member

Fixed in 1.3.3.

@akamor
Copy link
Contributor Author

akamor commented Apr 12, 2021

Just following up here that this issue doesn't not trigger on a table with 2B+ rows. Regardless the fix you submitted certainly seems reasonable but there is a chance it doesn't resolve the reported error. With that being said, I can not reproduce the issue now so perhaps it was transient. Thanks for all your assistance.

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

2 participants