Bug #25180 | Sub-select fails when table is locked | ||
---|---|---|---|
Submitted: | 19 Dec 2006 15:45 | Modified: | 10 Jan 2007 18:40 |
Reporter: | Karl Lloyd | Email Updates: | |
Status: | Duplicate | Impact on me: | |
Category: | MySQL Server: Locking | Severity: | S3 (Non-critical) |
Version: | 5.0.34-BK, 5.0.22 | OS: | Linux (Linux, ubuntu 6.06.2) |
Assigned to: | CPU Architecture: | Any |
[19 Dec 2006 15:45]
Karl Lloyd
[19 Dec 2006 18:52]
Valeriy Kravchuk
Thank you for a bug report. Verified just as described with 5.0.34-BK on Linux: mysql> CREATE TABLE `foo` ( -> `id` int(11) NOT NULL auto_increment, -> `at` timestamp NOT NULL default CURRENT_TIMESTAMP on update -> CURRENT_TIMESTAMP, -> `bar` varchar(15) NOT NULL, -> `pending` tinyint(1) NOT NULL default '0', -> `updated` tinyint(1) NOT NULL default '0', -> PRIMARY KEY (`id`) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.04 sec) mysql> INSERT INTO `foo` (`bar`, `pending`, `updated`) VALUES -> ('abcde', 1, 1), -> ('abcde', 1, 0), -> ('fghij', 1, 0), -> ('fghij', 0, 1), -> ('fghij', 0, 0), -> ('klmno', 0, 0), -> ('pqrst', 0, 0), -> ('pqrst', 0, 0), -> ('uvwxy', 0, 0); Query OK, 9 rows affected (0.01 sec) Records: 9 Duplicates: 0 Warnings: 0 mysql> LOCK TABLE `foo` WRITE; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM `foo` WHERE `bar` NOT IN (SELECT DISTINCT `bar` FROM `foo` -> WHERE `pending`=1) AND `updated`=0 LIMIT 1; ERROR 1100 (HY000): Table 'foo' was not locked with LOCK TABLES mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM `foo` WHERE `bar` NOT IN (SELECT DISTINCT `bar` FROM `foo` WHERE `pending`=1) AND `updated`=0 LIMIT 1; +----+---------------------+-------+---------+---------+ | id | at | bar | pending | updated | +----+---------------------+-------+---------+---------+ | 6 | 2006-12-19 17:26:12 | klmno | 0 | 0 | +----+---------------------+-------+---------+---------+ 1 row in set (0.01 sec) mysql> select version(); +--------------+ | version() | +--------------+ | 5.0.34-debug | +--------------+ 1 row in set (0.00 sec) Even if this is intended behaviour, error message looks misleading. So, it is a bug in any case.
[9 Jan 2007 18:10]
Steven Adams
This affects more than just subqueries; it affects UNIONs as well. Replace the original SELECT with this one: (SELECT * FROM `foo` WHERE `bar` IN ('abcde','fghij')) UNION (SELECT * FROM `foo` WHERE `bar` IN ('pqrst')); and the same results occur. Note that I am using version 4.1.21. When testing this same case in 4.0.27, it works. mysql> CREATE TABLE `foo` ( -> `id` int(11) NOT NULL auto_increment, -> `at` timestamp NOT NULL default CURRENT_TIMESTAMP on update -> CURRENT_TIMESTAMP, -> `bar` varchar(15) NOT NULL, -> `pending` tinyint(1) NOT NULL default '0', -> `updated` tinyint(1) NOT NULL default '0', -> PRIMARY KEY (`id`) -> ) ENGINE=MyISAM; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO `foo` (`bar`, `pending`, `updated`) VALUES -> ('abcde', 1, 1), -> ('abcde', 1, 0), -> ('fghij', 1, 0), -> ('fghij', 0, 1), -> ('fghij', 0, 0), -> ('klmno', 0, 0), -> ('pqrst', 0, 0), -> ('pqrst', 0, 0), -> ('uvwxy', 0, 0); Query OK, 9 rows affected (0.01 sec) Records: 9 Duplicates: 0 Warnings: 0 mysql> LOCK TABLE `foo` WRITE; Query OK, 0 rows affected (0.00 sec) mysql> (SELECT * FROM `foo` WHERE `bar` IN ('abcde','fghij')) UNION (SELECT * FROM `foo` WHERE `bar` IN ('pqrst')); ERROR 1100 (HY000): Table 'foo' was not locked with LOCK TABLES mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.00 sec) mysql> (SELECT * FROM `foo` WHERE `bar` IN ('abcde','fghij')) UNION (SELECT * FROM `foo` WHERE `bar` IN ('pqrst')); +----+---------------------+-------+---------+---------+ | id | at | bar | pending | updated | +----+---------------------+-------+---------+---------+ | 1 | 2007-01-09 12:02:15 | abcde | 1 | 1 | | 2 | 2007-01-09 12:02:15 | abcde | 1 | 0 | | 3 | 2007-01-09 12:02:15 | fghij | 1 | 0 | | 4 | 2007-01-09 12:02:15 | fghij | 0 | 1 | | 5 | 2007-01-09 12:02:15 | fghij | 0 | 0 | | 7 | 2007-01-09 12:02:15 | pqrst | 0 | 0 | | 8 | 2007-01-09 12:02:15 | pqrst | 0 | 0 | +----+---------------------+-------+---------+---------+ 7 rows in set (0.00 sec) mysql> select version(); +------------+ | version() | +------------+ | 4.1.21-log | +------------+ 1 row in set (0.00 sec)
[10 Jan 2007 12:29]
Karl Lloyd
Just to follow up on this further: interestingly, following a "LOCK TABLE `foo` WRITE;" the following query is successful: mysql> SELECT `at` FROM (SELECT * FROM `foo` WHERE `pending`=1) AS `baz` WHERE `updated` = 0; +---------------------+ | at | +---------------------+ | 2007-01-10 11:43:04 | | 2007-01-10 11:43:04 | +---------------------+ 2 rows in set (0.01 sec) but the following are not: mysql> SELECT `at`, (SELECT COUNT(*) FROM `foo` WHERE `pending`=1) AS `count` FROM `foo` WHERE `updated` = 1; ERROR 1100 (HY000): Table 'foo' was not locked with LOCK TABLES mysql> INSERT INTO `foo` (`at`, `bar`, `pending`, `updated`) (SELECT `at`, 'ABCDE', `pending`, `updated` FROM `foo` WHERE `pending` = 1 AND `updated` = 1); ERROR 1100 (HY000): Table 'foo' was not locked with LOCK TABLES mysql> SELECT * FROM `foo` ORDER BY (SELECT COUNT(`bar`) FROM `foo`); ERROR 1100 (HY000): Table 'foo' was not locked with LOCK TABLES (although I'm not sure of the extent of support for subselects within ORDER BY clauses) and, by adding another table: mysql> CREATE TABLE `bars` ( -> `id` int(11) NOT NULL auto_increment, -> `bar` varchar(15) NOT NULL, -> `pending` tinyint(1) NOT NULL default '0', -> `updated` tinyint(1) NOT NULL default '0', -> PRIMARY KEY (`id`) -> ) ENGINE=MyISAM; Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO `foo` (`bar`, `pending`, `updated`) VALUES -> ('abcde', 1, 1), -> ('abcde', 1, 0), -> ('fghij', 1, 0), -> ('fghij', 0, 1), -> ('fghij', 0, 0), -> ('klmno', 0, 0), -> ('pqrst', 0, 0), -> ('pqrst', 0, 0), -> ('uvwxy', 0, 0); Query OK, 9 rows affected (0.02 sec) Records: 9 Duplicates: 0 Warnings: 0 mysql> UPDATE `foo` SET `bar` = (SELECT REVERSE(`bar`) FROM `bars` WHERE `id` = 1) WHERE `pending` = 1 AND `updated` = 1; ERROR 1100 (HY000): Table 'bars' was not locked with LOCK TABLES mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.01 sec) mysql> DROP TABLE `bars`; Query OK, 0 rows affected (0.00 sec) mysql> DROP TABLE `foo`; Query OK, 0 rows affected (0.00 sec) Perhaps this is helpful info dev-wise.
[10 Jan 2007 12:33]
Karl Lloyd
Should have been "INSERT INTO `bars`" in my previous submission, of course.
[10 Jan 2007 14:40]
Dmitry Lenev
Hi, Karl! Thank you for your interest in MySQL! This report is duplicate of already known "Not a Bug" bug #5651. Altough I agree that this restriction is not very natural and error message can be improved. Feel free to add appropriate feature request!
[10 Jan 2007 16:33]
Karl Lloyd
Yes, I concede that in the last example (UPDATE with subselect) I should have locked both `foo` and `bars` and does indeed work when this is done. However, according to the documentation quoted in #5651 (http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html) the following should work: mysql> LOCK TABLES `foo` WRITE, `foo` `oof` WRITE; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM `foo` WHERE `bar` NOT IN (SELECT DISTINCT `bar` FROM `oof` WHERE `pending`=1) AND `updated`=0 LIMIT 1; ERROR 1100 (HY000): Table 'oof' was not locked with LOCK TABLES but doesn't. As this is different from my initial submission, and I think this IS a bug, perhaps I should submit this as a new report?
[10 Jan 2007 18:34]
Dmitry Lenev
Hi, Karl! Still this is not a bug. This query is not supposed to work as it refers to the aliased table incorrectly. Please re-read documentation, particularly pay attention to the example below: <quote> Conversely, if you lock a table using an alias, you must refer to it in your queries using that alias: mysql> LOCK TABLE t AS myalias READ; mysql> SELECT * FROM t; ERROR 1100: Table 't' was not locked with LOCK TABLES mysql> SELECT * FROM t AS myalias; </quote>
[10 Jan 2007 18:40]
Karl Lloyd
Apologies, my syntax was wrong. Many thanks for your help.