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

Use a subquery when filtering information_schema.tables by table_name. #39712

Conversation

arthurschreiber
Copy link
Contributor

Summary

This is a workaround for a MySQL bug we've encountered when using a database user that only has been granted SELECT permissions on a subset of the tables that exist in a given database.

When requesting data from the information_schema.tables without specifying a table name explicitly, MySQL only returns data for tables that can be accessed by the current user.

But when requested data with specifying a condition for a specific table, MySQL will return data even if the specified table can not be accessed by the current user.

We found out that using a subquery would make MySQL behave as expected. 🙈

Here's an example:

SELECT table_name FROM information_schema.tables WHERE table_schema = database()

This query will only return table names for tables where the current user has been granted SELECT.

SELECT table_name FROM information_schema.tables WHERE table_schema = database() AND table_name = 'some_table'

This query will return a single row containing 'some_table', if some_table exists but the current user has not been granted SELECT on it.

SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = database()) _subquery WHERE _subquery.table_name = 'some_table'

This query will return an empty result set if some_table exists but the current user has not been granted SELECT on it.

Other Information

We're not sure which versions of MySQL are affected by this (we know it exists on MySQL 5.7.28), but the proposed change should be compatible with all versions of MySQL

@arthurschreiber arthurschreiber force-pushed the arthur/use-subquery-for-information-schema branch 2 times, most recently from dd84a27 to 255e9c3 Compare June 24, 2020 16:51
@arthurschreiber
Copy link
Contributor Author

/cc @eileencodes

@eileencodes
Copy link
Member

Sorry I was unclear on your PR at GitHub. This should point at the master branch and then I'll backport to 6.0.

It looks like there's an issue with this, the mysql2 build is failing

/usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query': Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 (ActiveRecord::StatementInvalid)

@arthurschreiber arthurschreiber changed the base branch from 6-0-stable to master June 24, 2020 17:37
@arthurschreiber arthurschreiber force-pushed the arthur/use-subquery-for-information-schema branch from 255e9c3 to c900114 Compare June 24, 2020 17:38
@arthurschreiber
Copy link
Contributor Author

Sorry I was unclear on your PR at GitHub. This should point at the master branch and then I'll backport to 6.0.

I've changed this to point against master. 👍

It looks like there's an issue with this, the mysql2 build is failing

Yeah, there was a typo that I just fixed.

@eileencodes
Copy link
Member

I'm trying to think of a way to add a test for this but creating a user in a test to test this would be difficult. Do you know if the bug in mysql is documented? I think we should link to the bug if there is a report for it somewhere.

@arthurschreiber
Copy link
Contributor Author

Do you know if the bug in mysql is documented?

I don't think it is. I tried googling a bit, but could not find anything. I'll see if I can get around to open a report against MySQL as well.

@arthurschreiber
Copy link
Contributor Author

I filed a bug report with MySQL at https://bugs.mysql.com/bug.php?id=99981 with an easily reproducible test case. I also tested this against MySQL 8, and it looks like this particular bug was fixed starting 8.0.0.

@eileencodes eileencodes merged commit 0f6a4f5 into rails:master Jun 25, 2020
eileencodes added a commit that referenced this pull request Jun 25, 2020
…r-information-schema

Use a subquery when filtering `information_schema.tables` by `table_name`.
@eileencodes
Copy link
Member

Merged and backported to 6.0 in 0793a14

cgriego added a commit to cgriego/rails that referenced this pull request Oct 27, 2021
Depending on MySQL version and configuration, this is more than two
orders of magnitude slower than selecting only the two columns we need
for this query, which don't require reading any of the data files or
recalculating innodb stats.

https://dev.mysql.com/doc/refman/5.6/en/information-schema-optimization.html

Performance regression was introduced in rails#39712, before then the query
took around 40-50ms on my test environment, after it took 4-8s. With
this change it's back to 40-50ms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants