红联Linux门户
Linux帮助

打算使用MySQL,请高手介绍下它的主要缺点

发布时间:2011-04-30 10:32:52来源:红联作者:goldwing
比如access,超过2万条记录,检索变慢,长时间使用,文件越变越大等等,没有触发器,存储过程等等,当然它是桌面及引擎不能过多苛求,但MySQL呢?q):-s
文章评论

共有 6 条评论

  1. goldwing 于 2011-04-30 10:55:47发表:

    如果这些都不知道,就贸然学习,使用,一旦发现不可回避的问题,有人就要欲哭无泪了(3):os

  2. goldwing 于 2011-04-30 10:54:10发表:

    Mysql 5.0.51存在设计缺陷

    * 阅览次数: 今天:0 总浏览:461
    * 文章来源: http://www.typecho.net/archives/7/
    * 原文作者: Typecho官方日志
    * 整理日期: 2008-07-18
    * 发表评论

    * 字体大小:
    * 小
    * 中
    * 大

    今天在调试typecho的一个评论排序时发现无论我把排序规则设置为升序还是降序都无法改变最终的排序结果,在仔细检查我的语句后排除了语法出现问题的情况,因此将怀疑的目光定格到mysql上。我在开发中使用的是wamp套装,它集成的是mysql 5.0.51a,到wamp官方网站上发现5.0.51b的模块已经有了,下载下来安装,运行程序发现依然不好使。遂在google上搜索关键词"mysql order bug",第一条即是mysql官方网站上的bug记录,看来找到组织了。看了一下bug描述,跟我的情况差不多,主要是当语句中出现group by时,order by语句就会失效。

    在官方网站上对这个bug有较为详细的描述,我理解后大致意思如下:

    当我们在GROUP BY中使用主键时,mysql会首先忽略这个声明,因为mysql默认的就是按主键来GROUP BY的。但是如果GROUP BY和ORDER BY同时出现时,我估计是mysql的开发者尝试做一些语句上的优化,它会把GROUP BY里的主键值直接放到ORDER BY里面,而忘了检查GROUP BY和ORDER BY的这两个值是否相同,而且由于GROUP BY里面没有ASC/DESC的描述,写到ORDER BY里面以后同样也只有一个主键值,而在mysql中如果你不写ASC/DESC排序方法,它默认的就是按照ASC来排序,因此你得到排序就总是按主键的升序来排,无论你怎么调整ORDER BY都是这样。

    为了让大家理解这个bug,我来写一个问题重现,首先你要使用mysql 5.0.51x版本的数据库,然后请看以下操作和结果

    首先我们来看看升序

    mysql> SELECT `coid`, `created` FROM typecho_comments GROUP BY typecho_comments.
    `coid` ORDER BY typecho_comments.`created` ASC;
    +------+------------+
    | coid | created |
    +------+------------+
    | 1 | 1211300209 |
    | 2 | 1215627714 |
    +------+------------+
    2 rows in set (0.02 sec)

    没什么问题吧,再来看看降序

    mysql> SELECT `coid`, `created` FROM typecho_comments GROUP BY typecho_comments.
    `coid` ORDER BY typecho_comments.`created` DESC;
    +------+------------+
    | coid | created |
    +------+------------+
    | 1 | 1211300209 |
    | 2 | 1215627714 |
    +------+------------+
    2 rows in set (0.00 sec)

    查询结果没有任何变化,而且我们从查询时间也可以看出来,它是直接从缓存中读取的没有经过查询。为了证明我的观点,我们来个猛的

    mysql> SELECT `coid`, `created` FROM typecho_comments GROUP BY typecho_comments.
    `coid` DESC ORDER BY typecho_comments.`created` DESC;
    +------+------------+
    | coid | created |
    +------+------------+
    | 2 | 1215627714 |
    | 1 | 1211300209 |
    +------+------------+
    2 rows in set (0.00 sec)

    注意看我的语法,GROUP BY typecho_comments.`coid` DESC,这是一个明显错误的语法,但是如果mysql是直接将GROUP BY放到ORDER BY中的话,它将得到正确的执行。事实证明了我的猜测,而且它还“正确”地倒序了!!

    解决方案

    升级到mysql 5.0.52以上版本或者降级到mysql 5.0.45以下版本即可。

  3. goldwing 于 2011-04-30 10:52:22发表:

    http://dev.mysql.com/doc/refman/5.1/zh/restrictions.html

  4. goldwing 于 2011-04-30 10:50:46发表:

    今天看到手册,不小心看到了这里,自己做了几个例子。
    从MYSQL4.x开始,MYSQL就增加了以每个用户为基础,限制MYSQL服务器的资源利用。

    自己查看MYSQL.USER 表就会发现里面最后几个字段:
    mysql> select version();
    +------------------------------------+
    | version() |
    +------------------------------------+
    | 5.1.17-beta-community-nt-debug-log |
    +------------------------------------+
    1 row in set (0.00 sec)

    *************************** 36. row ***************************
    Field: max_questions
    Type: int(11) unsigned
    Null: NO
    Key:
    Default: 0
    Extra:
    *************************** 37. row ***************************
    Field: max_updates
    Type: int(11) unsigned
    Null: NO
    Key:
    Default: 0
    Extra:
    *************************** 38. row ***************************
    Field: max_connections
    Type: int(11) unsigned
    Null: NO
    Key:
    Default: 0
    Extra:
    *************************** 39. row ***************************
    Field: max_user_connections
    Type: int(11) unsigned
    Null: NO
    Key:
    Default: 0
    Extra:
    39 rows in set (0.00 sec)

    这三个字段可以用GRANT语句来生成。
    1、MAX_QUERIES_PER_HOUR 用来限制用户每小时运行的查询数量
    mysql> grant select on *.* to 'cu_blog'@'localhost' identified by '123456' with
    max_queries_per_hour 5;
    Query OK, 0 rows affected (0.00 sec)
    ...
    mysql> select user();
    +-------------------+
    | user() |
    +-------------------+
    | cu_blog@localhost |
    +-------------------+
    1 row in set (0.00 sec)
    当到了指定的次数时就会报错
    mysql> select user();
    ERROR 1226 (42000): User 'cu_blog' has exceeded the 'max_questions' resource (cu
    rrent value: 5)
    2、MAX_UPDATES_PER_HOUR 用来限制用户每小时的修改数据库数据的数量。
    mysql> grant select on *.* to 'cu_blog'@'localhost' with max_updates_per_hour 5;
    Query OK, 0 rows affected (0.00 sec)
    3、MAX_CONNECTIONS_PER_HOUR用来控制用户每小时打开新连接的数量。
    mysql> grant select on *.* to 'cu_blog'@'localhost' with max_connections_per_hou
    r 5;
    Query OK, 0 rows affected (0.00 sec)
    4、MAX_USER_CONNECTIONS 限制有多少用户连接MYSQL服务器。
    mysql> grant select on *.* to 'cu_blog'@'localhost' with max_user_connections 2;

    Query OK, 0 rows affected (0.00 sec)

    5、要想将所有账户当前的记数重设为零,可以执行FLUSH USER_RESOURCES语句。还可以通过重载授权表来重设记数。
    mysql> flush user_resources;
    Query OK, 0 rows affected (0.00 sec)

  5. goldwing 于 2011-04-30 10:47:38发表:

    mysql的默认配置确实比较差劲,也没做最基本的优化调整。
    现在的服务器,即使是办公用的PC,内存也大多1~2G了吧,默认配置分配给innodb的buffer pool才8M,真是服了,多少年了,也不改改。
    还有另一个害人的地方是innodb数据文件的默认大小是10M,这个一般情况下,建议至少大于256M或512M。

  6. goldwing 于 2011-04-30 10:45:29发表:

    如果WEHERE子句的查询条件里有不等号(WHERE coloum != ...),MySQL将无法使用索引。
    类似地,如果WHERE子句的查询条件里使用了函数(WHERE DAY(column) = ...),MySQL也将无法使用索引。
    在JOIN操作中(需要从多个数据表提取数据时),MySQL只有在主键和外键的数据类型相同时才能使用索引。
    如果WHERE子句的查询条件里使用比较操作符LIKE和REGEXP,MySQL 只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说,如果查询条件是LIKE 'abc%',MySQL将使用索引;如果查询条件是LIKE '%abc',MySQL将不使用索引。
    在ORDER BY操作中,MySQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。(虽然如此,在涉及多个数据表查询里,即使有索引可用,那些索引在加快ORDER BY方面也没什么作用)