2009-11-23

数据库字段设计错误导致的系统BUG

Views: 24006 | Add Comments

Yii的AR类, 可以在rules()函数中声明验证规则. 但指定了验证规则, 也可以不使用. 在调用save()方法时, 如何第一个参数为false(默认为true), 则不进行验证. 一旦验证失败, 将立即返回, 不保存数据. Yii提供的工具可以根据数据库表定义自动生成验证规则. AR类的验证规则的另一个功能是用于自动生成HTML页面表单. 但是, 根据实际使用情况, Yii所提供的这个功能在XXX项目中几乎已经成为鸡肋, 都是在开发者不知情的情况下使用了.

Yii的这个特性, 加上数据库表设计的失误, 以及代码逻辑问题, 导致某个功能出现BUG.

代码的功能是这样的: 调用AR类的save()方法保存一条记录, 然后跳转到该记录的详细信息页面. 实际操作时, 偶尔出现记录未保存, 然后跳转URL里的id参数为空. 代码逻辑如下:

if($ar->save()){
    // do something
}
redirect($ar->id);

显然, 代码逻辑没有错误处理, 无论成功与否, 都跳转. 下面再分析保存失败的原因.

数据库表定义中, 备注字段的类型为VARCHAR(255), 如何短的字符串类型的应用范围一般很窄, 再加上所对应的业务字段是备注信息, 往往是大段的文本, 所以, 数据库设计已经失败, 出错是必然的. 另外, 程序逻辑无论是客户端还是服务器端, 都没有再做业务层的验证给出错误提示, 而是无意地使用了Yii框架的AR类的验证机制. 综合上述原因, BUG的查找花费了不少的时间.

总结:

1. 数据库设计

通过对数据库表字段的仔细选择来获取性能, 对于XXX系统, 这种方式已经过时. 一般只有如下几种数据类型: 数字, 字符串(varchar), 文本(长字符串, text), 时间.

结合 MySQL, 数字主要使用int, 像tiny int, middle int之类的整数类型, 只是节省空间考虑, 速度上反而比int类型要慢, 当数值较大时, 使用bigint. 对XXX, 除了int和bigint, 其它的整数类型都没有必要.

对于字符串和文本类型, 如果不建立索引作为查询条件, 一般使用text, 不要使用varchar, 如果文本较长, 则使用longtext. 如果字段对应的输入框是多行文本框, 那么就没有使用varchar的必要了. 建议原则是: 不建立索引的字符串使用text, 格式化输入框(HTML编辑控件)对应的字段使用longtext, 只有建立索引的字符串才使用varchar.

2. AR类设计

把AR类中的rules()函数删除.

3. 客户端验证

在客户端也做验证, 并在出错时提示用户. 如用户输入的文本过长, 等等.

Related posts:

  1. 如何让 PHP json_encode 函数不转义中文?
  2. JSP中文乱码解决之道
  3. MySQL命令行按Delete键输出”~”的问题
  4. MySQL binlog查看和清理
  5. Linux下编译安装Apache/Nginx/Lighttpd+PHP+MySQL
Posted by ideawu at 2009-11-23 16:58:12 Tags:

Leave a Comment