Bug #64992 | Temporary table in a database on a read-only instance can be overwritten | ||
---|---|---|---|
Submitted: | 16 Apr 2012 11:02 | Modified: | 10 Aug 2012 1:35 |
Reporter: | Tomokazu YONETANI | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: DDL | Severity: | S3 (Non-critical) |
Version: | 5.5.21, 5.0.97, 5.1.63, 5.524, 5.6.6 | OS: | Linux (SL 6.1(x86_64)) |
Assigned to: | CPU Architecture: | Any |
[16 Apr 2012 11:02]
Tomokazu YONETANI
[16 Apr 2012 16:50]
Sveta Smirnova
Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://dev.mysql.com/doc/ and the instructions on how to report a bug at http://bugs.mysql.com/how-to-report.php According to http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_read_only: "When it is enabled, the server permits no updates except from users that have the SUPER privilege or (on a slave server) from updates performed by slave threads. " This definition says nothing about DDL statements.
[17 Apr 2012 0:31]
Tomokazu YONETANI
Hi, thank you for pointing out that I chose a wrong category or terminology. Since it doesn't seem like you read the description because of that, here's a shorter version; if this still doesn't make sense, well, I'll give up. Normally, a user without SUPER privilege cannot create a regular table if mysqld is running in read-only mode. BUT he can create a temporary table on the same database, is this correct? AND he can define a regular table with the same name as the temporary table within the same session, and that regular table remains on that database, is this correct?
[17 Apr 2012 8:47]
Sveta Smirnova
Thank you for the feedback. You are right: I granted SUPER privilege for my test user occasionally. But INSERT into temporary table should not fail. Anyway verified as described.
[17 Apr 2012 22:32]
Davi Arnaut
Temporary tables are removed when the session disconnects, so you are basically trying to insert into a base table. Also, read_only does apply to DDL statements.
[18 Apr 2012 10:48]
Jon Olav Hauglid
Like Davi says, INSERT should fail after re-connecting since the temporary table is then gone. The real problem here is CREATE TABLE after first creating a temporary table. # Make non-SUPER user GRANT SELECT ON *.* TO test@localhost; SET GLOBAL read_only= 1; --connect(con1, localhost, test) # This should fail --error ER_OPTION_PREVENTS_STATEMENT CREATE TABLE t1(a INT, b INT); # This should work CREATE TEMPORARY TABLE t1(a INT); # This should still fail, but doesn't CREATE TABLE t1(a INT, b INT); # Cleanup --connection default SET GLOBAL read_only= 0; --disconnect con1 DROP USER test@localhost; DROP TABLE t1;
[18 Apr 2012 18:53]
Sveta Smirnova
Jon Olav, please see this: mysql> create temporary table t(id bigint unsigned not null primary key); Query OK, 0 rows affected (0.00 sec) mysql> desc t; +-------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+-------+ | id | bigint(20) unsigned | NO | PRI | NULL | | +-------+---------------------+------+-----+---------+-------+ 1 row in set (0.00 sec) mysql> insert into t(id)values(0); ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement This insert supposed to go into temporary table and should not fail. Even if there is existent persistent table. I can not repeat this issue.
[19 Apr 2012 6:49]
Jon Olav Hauglid
Sveta, me neither. Which leaves the problem I made the above MTR test case for.
[19 Apr 2012 6:54]
Davi Arnaut
Looks like the remaining issue is a duplicate of Bug#62008 (binary log enabled and transactional temp table). There are also bug reports about temp tables shadowing base tables.
[10 May 2012 9:49]
zhai weixiang
deny_updates_if_read_only_option() was used to check if a query was allowed to excute. if we first create a temporary table and then create a real table, the later operation will be allowed. i guess there must be some problem with the following code in deny_updates_if_read_only_option() const my_bool update_real_tables= some_non_temp_table_to_be_updated(thd, all_tables) && !(create_temp_tables || drop_temp_tables); Generally some_non_temp_table_to_be_updated() should return true and create_temp_tables equals zero while we are creating a real table. but actully the return value of some_non_temp_table_to_be_updated() is 0, because the same table name was found in temporary table list. function some_non_temp_table_to_be_updated: static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables) { for (TABLE_LIST *table= tables; table; table= table->next_global) { DBUG_ASSERT(table->db && table->table_name); if (table->updating && !find_temporary_table(thd, table)) return 1; } return 0; } so i think the value of update_real_tables should be calculated like this : const my_bool update_real_tables= (lex->sql_command == SQLCOM_CREATE_TABLE || some_non_temp_table_to_be_updated(thd, all_tables)) && !(create_temp_tables || drop_temp_tables); I don't know my guess is correct , but this small change really works
[10 Aug 2012 1:35]
Paul DuBois
Noted in 5.7.0 changelog. If read_only is enabled, it is still permitted to create TEMPORARY tables. But in this case, a non-TEMPORARY table with the same name could also be created, which should not be permitted.