本帖最后由 mark35 于 2012-12-3 20:22 编辑
为啥DiscuzX大家都觉得慢呢?
除开因开启新增功能导致的性能损失,某些代码也会造成性能下降
如果你DiscuzX2的 config_global.php文件中是这样的:- $_config['security']['querysafe']['status'] = 1;
复制代码 那么在执行每条SQL前都会对此字符串调用下面函数进行过滤:
- function _do_query_safe($sql) {
- static $_CONFIG = null;
- if($_CONFIG === null) {
- $_CONFIG = getglobal('config/security/querysafe');
- }
- $sql = str_replace(array('\\\\', '\\\'', '\"', '\'\''), '', $sql);
- $mark = $clean = '';
- if(strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false) {
- $clean = preg_replace("/'(.+?)'/s", '', $sql);
- } else {
- $len = strlen($sql);
- $mark = $clean = '';
- // 逐字扫描的大坨代码开始~
- for ($i = 0; $i <$len; $i++) {
- $str = $sql[$i];
- switch ($str) {
- case '\'':
- if(!$mark) {
- $mark = '\'';
- $clean .= $str;
- } elseif ($mark == '\'') {
- $mark = '';
- }
- break;
- case '/':
- if(empty($mark) && $sql[$i+1] == '*') {
- $mark = '/*';
- $clean .= $mark;
- $i++;
- } elseif($mark == '/*' && $sql[$i -1] == '*') {
- $mark = '';
- $clean .= '*';
- }
- break;
- case '#':
- if(empty($mark)) {
- $mark = $str;
- $clean .= $str;
- }
- break;
- case "\n":
- if($mark == '#' || $mark == '--') {
- $mark = '';
- }
- break;
- case '-':
- if(empty($mark)&& substr($sql, $i, 3) == '-- ') {
- $mark = '-- ';
- $clean .= $mark;
- }
- break;
- default:
- break;
- }
- $clean .= $mark ? '' : $str;
- }
- }
- $clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/"]+/is", "", strtolower($clean));
- if($_CONFIG['afullnote']) {
- $clean = str_replace('/**/','',$clean);
- }
- if(is_array($_CONFIG['dfunction'])) {
- foreach($_CONFIG['dfunction'] as $fun) {
- if(strpos($clean, $fun.'(') !== false) return '-1';
- }
- }
- if(is_array($_CONFIG['daction'])) {
- foreach($_CONFIG['daction'] as $action) {
- if(strpos($clean,$action) !== false) return '-3';
- }
- }
- if($_CONFIG['dlikehex'] && strpos($clean, 'like0x')) {
- return '-2';
- }
- if(is_array($_CONFIG['dnote'])) {
- foreach($_CONFIG['dnote'] as $note) {
- if(strpos($clean,$note) !== false) return '-4';
- }
- }
- return 1;
- }
复制代码 看到其中的 最大坨的那个 for 循环块没?这段代码意味着将会对整个SQL字符串逐字符(8bit)进行搜索处理。SQL越长当然执行时间越久。再加上前后的多条preg_replace, PHP毕竟不是在字符串处理及正则处理有特长的PERL,这种处理多少会降低php进程执行效率。
也许使用 mysql_real_escape_string() 更为合适。
因为addslashes() 函数在处理多字节字符串时可能会有疏漏。
在这点上postgresq安全性更高:自v9.1 开始对于通过 \ 转义的字符默认不再解析,即 \ 字符不再是转义字符用,而是一个合法字符。对于单引号的转义按照SQL标准从 \' 改为 '' (两个单引号)。
这是 pgsql v8.2的帮助文档:
standard_conforming_strings (boolean)
控制普通字符串文本('...')中是否按照 SQL 标准把反斜扛当普通文本。缺省为 off ,表示反斜扛当作逃逸对待。将来的版本会把这个设置的缺省值改成 on ,这样字符串文本的语法就变为符合标准了。应用可以检查这个参数来判断字符串文本如何被处理。建议明确使用逃逸字符串语法(E'...')来逃逸字符。
pgsql v9.1的:
standard_conforming_strings (boolean)
This controls whether ordinary string literals ('...') treat backslashes literally, as specified in the SQL standard. Beginning in PostgreSQL 9.1, the default is on (prior releases defaulted to off). Applications can check this parameter to determine how string literals will be processed. The presence of this parameter can also be taken as an indication that the escape string syntax (E'...') is supported. Escape string syntax (Section 4.1.2.2) should be used if an application desires backslashes to be treated as escape characters.
http://www.postgresql.org/docs/9 ... fig-compatible.html
|