-
Notifications
You must be signed in to change notification settings - Fork 548
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
Save affected_rows on the wrapper when reading results #1383
Conversation
Between fetching the result and accessing the affected_rows property, GC might have been triggered and might have freed some Mysql2::Statement objects. This calls mysql_stmt_close which resets the connection affected_rows to -1, which in turn is treated as an error when calling mysql_affected_rows. ``` client.query("SELECT 1") client.affected_rows # raises Mysql2::Error ```
Ref: brianmario/mysql2#1383 The proper fix can only be upstream, however we can reduce the likeliness of hitting the bug by only calling `#affected_rows` when strictly necessary, meaning when we performed a query that didn't return a result set.
Ref: brianmario/mysql2#1383 The proper fix can only be upstream, however we can reduce the likeliness of hitting the bug by only calling `#affected_rows` when strictly necessary, meaning when we performed a query that didn't return a result set. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
Ref: brianmario/mysql2#1383 If we eagerly close uncached statements, we drastically reduce the risk of one of them being GCed between `#query` and `#affected_rows`. The bug is still there thouhg, and can happen when `#execute` is used.
Ref: brianmario/mysql2#1383 The proper fix can only be upstream, however we can reduce the likeliness of hitting the bug by only calling `#affected_rows` when strictly necessary, meaning when we performed a query that didn't return a result set. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
Ref: brianmario/mysql2#1383 If we eagerly close uncached statements, we drastically reduce the risk of one of them being GCed between `#query` and `#affected_rows`. The bug is still there thouhg, and can happen when `#execute` is used.
Ref: brianmario/mysql2#1383 The proper fix can only be upstream, however we can reduce the likeliness of hitting the bug by only calling `#affected_rows` when strictly necessary, meaning when we performed a query that didn't return a result set. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
Ref: brianmario/mysql2#1383 If we eagerly close uncached statements, we drastically reduce the risk of one of them being GCed between `#query` and `#affected_rows`. The bug is still there thouhg, and can happen when `#execute` is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great.
@@ -1155,12 +1157,12 @@ static VALUE rb_mysql_client_session_track(VALUE self, VALUE type) { | |||
* if it was an UPDATE, DELETE, or INSERT. | |||
*/ | |||
static VALUE rb_mysql_client_affected_rows(VALUE self) { | |||
my_ulonglong retVal; | |||
uint64_t retVal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see the type changed between MySQL 5.7 and 8.0:
https://dev.mysql.com/doc/c-api/8.0/en/mysql-affected-rows.html
uint64_t
mysql_affected_rows(MYSQL *mysql)
https://dev.mysql.com/doc/c-api/5.7/en/mysql-affected-rows.html
my_ulonglong
mysql_affected_rows(MYSQL *mysql)
Between fetching the result and accessing the affected_rows property, GC might have been triggered and might have freed some Mysql2::Statement objects. This calls mysql_stmt_close which resets the connection affected_rows to -1, which in turn is treated as an error when calling mysql_affected_rows.
cc @matthewd @zzak (This is what is causing the flaky test on Rails).
@tenderlove You think you could merge and release this? This bugs make prepare statements fundamentally unsafe to use....