我已经做了大量的搜索和故障排除,试图自己解决这个问题。
我的情况是我已经从Debian Lenny(5.0-ish)更新了Debian Squeeze(MySQL 5.1.49)的主机,并且返回预期结果的先前工作查询现在返回一个空集。
所以这里是背景。为了查看数据是否有问题,我做了一个数据库的mysqldump。然后我将其复制到我的开发机器(通过Homebrew安装MySQL的Mac OS X 10.6.8)并在那里设置数据库。查询返回了预期的结果!
代码基于一个开源应用程序,所以我回去并在Lenny主机上做了一个干净的安装和数据库引导程序。我确认查询返回了预期的内容。
我还在Squeeze上的干净安装(未升级的主机)上重新安装了该应用程序。开源应用程序的Squeeze上的全新安装按预期工作。
我在Lenny的应用程序的全新安装上做了一个mysqldump。然后,我在干净的Squeeze主机上创建了一个新数据库,并将Lenny转储加载到其中。查询不再返回预期结果。与数据库升级到Squeeze的情况相同。
以下是对数据的处理方式的描述。
首先是表格:
mysql> describe roles;
+-------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(40) | YES | | NULL | |
| authorizable_type | varchar(30) | YES | | NULL | |
| authorizable_id | int(11) | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+-------------------+-------------+------+-----+---------+----------------+
mysql> describe roles_users;
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| user_id | int(11) | YES | MUL | NULL | |
| role_id | int(11) | YES | MUL | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+------------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)
你猜对了,这些是来自Rails 2.1ish的授权插件。现在由一个已经升级到Rails 2.3.5的应用程序使用。
我已经确认两台主机上的表格描述相同。
接下来的数据:
mysql> select * from roles where id = 1;
+----+------------+-------------------+-----------------+---------------------+---------------------+
| id | name | authorizable_type | authorizable_id | created_at | updated_at |
+----+------------+-------------------+-----------------+---------------------+---------------------+
| 1 | site_admin | Basket | 1 | 2009-05-27 00:14:22 | 2009-05-27 00:14:22 |
+----+------------+-------------------+-----------------+---------------------+---------------------+
1 row in set (0.00 sec)
mysql> select * from roles_users where role_id = 1 and user_id = 1;
+---------+---------+---------------------+---------------------+
| user_id | role_id | created_at | updated_at |
+---------+---------+---------------------+---------------------+
| 1 | 1 | 2009-05-27 00:14:22 | 2009-05-27 00:14:22 |
+---------+---------+---------------------+---------------------+
1 row in set (0.00 sec)
同样,两个主机都返回相同的结果。
以下是要返回的查询(由授权插件构造以验证用户在系统中的正确对象上具有正确的角色):
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
再次,在Debian Squeeze主机上,返回空集:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
Empty set (0.00 sec)
有什么想法吗?还有其他人经历过这个吗?
对于评论请求的结果更新:
这里没有LIMIT 1:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 ));
Empty set (0.00 sec)
这里从where子句中删除roles_users.user_id = 1:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`id` = 1 ;
+----+
| id |
+----+
| 1 |
...
3 rows in set (0.00 sec)
以上是上述查询,但在select:
中显示了roles_users.user_idmysql> SELECT `roles`.id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`id` = 1 ;
+----+---------+
| id | user_id |
+----+---------+
| 1 | 1 |
...
3 rows in set (0.00 sec
最后这里从where子句中删除roles.id,但保留roles_users.user_id:
mysql> SELECT `roles`.id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles_users`.user_id = 1;
+----+---------+
| id | user_id |
+----+---------+
...
| 1 | 1 |
...
9 rows...
答案 0 :(得分:0)
我找到了导致这个问题发生在Debian Squeeze MySQL 5.1.49上的根本原因;当roles_users表具有多个role_id的不同user_id时,查询将返回一个空集。
即。如果我有这个:
mysql> SELECT `roles_users`.role_id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id order by role_id;
+---------+---------+
| role_id | user_id |
+---------+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 2 |
+---------+---------+
6 rows in set (0.01 sec)
我得到了我对此的期望:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1) AND ((`roles_users`.user_id = 1)) LIMIT 1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
但是当我有这个(添加了具有role_id 1的user_id)时:
mysql> SELECT `roles_users`.role_id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id order by role_id;
+---------+---------+
| role_id | user_id |
+---------+---------+
| 1 | 1 |
| 1 | 5 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 4 | 5 |
| 5 | 1 |
| 6 | 2 |
+---------+---------+
8 rows in set (0.00 sec)
我明白了:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
Empty set (0.00 sec)
所以有两种可能性。
使用该数据集的查询(多个具有相同role_id的user_id)始终无效,并且MySQL 5.0.51a-24 + lenny4无论如何都使用它,即使它不应该有OR有一个MySQL 5.1.49-3(Debian)中的错误。
我将在论坛上报告MySQl上的错误,看看我得到了什么回应。
答案 1 :(得分:0)
要解决问题,请在Squeeze上升级到5.1.58-1~dotdeb.1。我使用了dotdeb,因为没有Squeeze后向版本的MySQL。
以下是我的基本步骤(以root身份):
cp /etc/mysql/my.cnf至临时位置仅在您有自定义配置时必须
aptitude purge libmysqlclient-dev libmysqlclient16 mysql-client mysql-client-5.1 mysql-common mysql-server mysql-server-5.1 mysql-server-core-5.1
根据http://www.dotdeb.org/instructions/设置/etc/apt/sources.list.d/dotdeb.list
如果你有如上所述的自定义配置,则必须:
这使我的查询返回预期的id而不是空集。