RZZONE---技术文档|精美图片|优秀网站收藏|友情连接|源码下载|教程|网站制作|网站建设|优秀设计 http://www.rzzone.net/rss.php utf-8 weboo.r|weboo630@163.com 2009-01-06 批量生成html的方法 http://www.rzzone.net/docdetail.php?id=195 方法,写出来大家指点一下:
首先在smartt.class.php中为Smarty类添加这么一个方法:
PHP代码:
//参数一:html文件保存路径,参数2:写入的内容
function MakeHtmlFile($file_name$c

{  
      if(!
$fp fopen($file_name"wa"
))
      {     
         echo 
"文件打开失败!"
;     
         return 
false
;     
      }     
      if(!
fwrite($fp$c
))
      {     
         echo 
"文件写入失败!"
;     
         
fclose($fp
);     
         return 
false
;     
      }             
      
fclose($fp
);     
   }


问题:我的所有文章都调用的是news.tpl这个模板,那么究竟如何批量生成呢?

我们先看看news.php
PHP代码:

<?php
include_once("config.php"
);
include_once(
"init.php"
);
$s->assign("title","所有的新闻分类"
);
$ID=$_GET["ID"]+0
;
$sql="select * from artical where newsID=$ID"
;
$rs=$db->fetch($sql
);
$s->assign("news",$rs["rec"][0]);
//注意:$rs["rec"][0]是个数组
$s->display("news.html"
);
?>

整个模板变量就只有$news,这么写有什么好处呢?我可以以数组的方式读取内容

那么究竟如何生成:
看如下代码:
很简单的
PHP代码:

<?php
include_once("config.php"
);
include_once(
"init.php"
);
$sql="select * from artical"
;
$rs=$db->fetch($sql
);
foreach (
$rs["rec"] as $k=>$v
)
{
$s->assign("news",$v
);
$s->MakeHtmlFile("./news/news_".$v[0].".html",$s->fetch("news.html",nullnullfalse
));
}
?>

很简单把!

PHP代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "[url=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd[/url]">
<
html xmlns="[url=http://www.w3.org/1999/xhtml]http://www.w3.org/1999/xhtml[/url]"
>
<
head
>
<
meta http-equiv="Content-Type" content="text/html; charset=gb2312" 
/>
<
title><{$news.titles}></title
>
<
link href="<{$docroot}>/CSS/main.css" rel="stylesheet" type="text/css" 
/>
</
head
>
<
body
>
<
table width="800" border="0" align="center" cellpadding="0" cellspacing="0" style="border:solid #CCCCCC 1px"
>
  <
tr
>
    <
td height="25" colspan="6" align="center" bgcolor="#eeeeee"><strong><{$news.titles}></strong></td
>
  </
tr
>
  <
tr
>
    <
td width="74" height="25" align="right">作者:</td
>
    <
td width="220"><{$news.author}></td
>
    <
td width="40" align="right">时间:</td
>
    <
td width="134" align="left"><{$news.sj}></td
>
    <
td width="110" align="right">关键词:</td
>
    <
td width="220" align="left"><{$news.keyword}></td
>
  </
tr
>
  <
tr
>
    <
td height="25" align="right" >核心提示:</td
>
    <
td height="25" colspan="5" class="artical" style="border:double #FF0000 3px;"><{$news.sumary}></td
>
  </
tr
>
  <
tr
>
    <
td height="25" colspan="6" align="left" class="artical" style="padding:10px;"><{$news.contents}></td
>
  </
tr
>
</
table
>
</
body
>
</
html>

总结:主要使用smarty的fetch方法,和文件的读写操作

]]>
索引的作用 http://www.rzzone.net/docdetail.php?id=194 索引提供指针以指向存储在表中指定列的数据值,然后根据指定的排序次序排列这些指针。数据库使用索引的方式与使用书的目录很相似:通过搜索索引找到特定的值,然后跟随指针到达包含该值的行。
在数据库关系图中,可以为选定的表创建、编辑或删除索引/键属性页中的每个索引类型。当保存附加在此索引上的表或包含此表的数据库关系图时,索引同时被保存。
通常情况下,只有当经常查询索引列中的数据时,才需要在表上创建索引。索引将占用磁盘空间,并且降低添加、删除和更新行的速度。不过在多数情况下,索引所带来的数据检索速度的优势大大超过它的不足之处。然而,如果应用程序非常频繁地更新数据,或磁盘空间有限,那么最好限制索引的数量。
在创建索引前,必须确定要使用的列和要创建的索引类型。
索引类型
索引列
可基于数据库表中的单列或多列创建索引。当某些行中的某一列具有相同的值时,多列索引能区分开这些行。
如果经常在同时搜索两列或多列或按两列或多列排序时,索引也很有帮助。例如,如果经常在同一查询中为姓和名两列设置准则,那么在这两列上创建多列索引将很有意义。
确定索引的有效性:
检查查询中的 WHERE 和 JOIN 子句。在任一子句中包括的每一列都是索引可以选择的对象。
试验新的索引,检查它对运行查询性能的影响。
考虑表中已创建的索引数量。最好不要在一个表中创建大量的索引。
检查表中已创建的索引定义。最好避免包含共享列的重叠索引。
检查列中唯一数据值的数量,并与表中的行数进行比较。比较的结果就是该列的可选择性,这有助于确定该列是否适合建立索引,如果适合,确定索引的类型是什么。
索引类型
根据数据库的功能,可在数据库设计器中创建三种类型的索引 — 唯一索引、主键索引和聚集索引。
唯一索引
唯一索引不允许两行具有相同的索引值。
如果现有数据中存在重复的键值,则大多数数据库都不允许将新创建的唯一索引与表一起保存。当新数据将使表中的键值重复时,数据库也拒绝接受此数据。例如,如果在 employee 表中的职员姓氏 (lname) 列上创建了唯一索引,则所有职员不能同姓。
主键索引
数据库表通常有一列或列组合,其值用来唯一标识表中的每一行。该列称为表的主键。
在数据库关系图中为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。主键索引要求主键中的每个值是唯一的。当在查询中使用主键索引时,它还允许快速访问数据。。
聚集索引
在聚集索引中,表中各行的物理顺序与键值的逻辑(索引)顺序相同。表只能包含一个聚集索引。
如果不是聚集索引,表中各行的物理顺序与键值的逻辑顺序不匹配。聚集索引比非聚集索引有更快的数据访问速度。一个天才顶不上十个笨蛋!]]>
php一维数组的简单排序 http://www.rzzone.net/docdetail.php?id=193 <?php
//冒泡排序
function bubbleSort($array)
{
for( $out=count($array)-1;$out>0;$out-- )
{
   for( $in=0;$in<$out;$in++ )
   {
    if( $array[$in] > $array[$in+1] )
    {
     $temp = $array[$in];
     $array[$in] = $array[$in+1];
     $array[$in+1] = $temp;
    }
   }
}

return $array;
}

//选择排序
function selectionSort($array)
{
for( $out=0;$out<count($array);$out++ )
{
   $min = $out;
   for( $in=$out+1;$in<count($array);$in++ )
   {
    if( $array[$in] < $array[$min] )
    {
     $min = $in;
    }
   }
   if($min != $out )
   {
    $temp = $array[$out];
    $array[$out] = $array[$min];
    $array[$min] = $temp;
   }
}

return $array;
}

//插入排序
function insertionSort($array)
{
for($out=1;$out<count($array);$out++)
{
   $temp = $array[$out];
   $in = $out;
   while( $in>=0 && $array[$in-1]>$temp )
   {
    $array[$in] = $array[$in-1];
    --$in;
   }
   $array[$in] = $temp;
}

return $array;
}

?>

]]>
千万级记录的Discuz论坛导致MySQL CPU 100%的解决方案(转) http://www.rzzone.net/docdetail.php?id=192 解决一个拥有 60 万条记录的 MySQL 数据访问时,导致 MySQL CPU 占用 100% 的经过。在解决问题完成优化(optimize)之后,我发现 Discuz 论坛也存在这个问题,当时稍微提了一下: " r/ G$ m, u# w: {+ o! J

' g& q. \: s7 t- h4 c3 B$ @发现此主机运行了几个 Discuz 的论坛程序, Discuz论坛的好几个表也存在着这个问题。于是顺手一并解决,cpu占用再次降下来了。
3 {; `" D) r0 N6 W3 l3 s; y, D& u# C* K2 C
   前几天,一位朋友通过这篇文章找到了我,说他就是运行最新的 discuz 版本,MySQL 占用 CPU 100%,导致系统假死,每天都要重启好几次,花了一个多月的时间一直没有解决,希望我帮忙一下。经过检查,他的这个论坛最重要的几个表中,目前 cdb_members 表,有记录 6.2 万;cdb_threads 表,有记录 11万;cdb_posts表,有记录 1740 万;所有数据表的记录加起来,超过 2000 万;数据库的大小超过 1GB。经过半天的调试,总算完成了 discuz 论坛优化,
9 q  W/ m$ v. \1 v/ o7 ]4 x
& A" k, Z1 W; M6 w2 Q% R; Q- G5 ]$ A) D
   2007年3月我发现 discuz 论坛的数据库结构设计有一些疏忽,有许多查询子句的条件比较,都没有建立 Index 索引。当时我所检查的那个数据表,记录只有几千条,因此对 CPU 负荷不大。现在这个数据库表,上千万的记录检索,可以想象,如果数据表结构设计不规范,没有提供索引,所耗费的时间是一个恐怖的数字。
  W9 \. x: i7 k5 ]  为了调试方便,我从 dizcus 的官网下载了其最新的 Dizcus! 5.5.0 论坛程序.# U5 A. v$ q( P0 l6 n& c, B

5 m' c0 x( U7 D' m  我首先检查了 my.ini 的参数配置,一切正常。进入 MySQL 的命令行,调用 show processlist 语句,查找负荷最重的 SQL 语句,结合 Discuz 论坛的源码,发现有以下语句导致 CPU 上升:
+ U- u; C# a- c* Q: X" M5 @! s# d1 z0 q
( O% \# i8 ^1 Dmysql> show processlist;9 s$ b* \. Z% M' e/ i6 V4 z) L
+-----+------+----------------+---------+---------+------+------------+---------5 f  `1 m( H3 b/ J
-----------------------------------------------------------------+. S3 Z# x0 i% f* s( D& A  ?
| Id  | User | Host           | db      | Command | Time | State      | Info" B. ~6 U; M, h% F/ z9 `6 `
                                                                 |$ A# @; r( ^' c6 w) q6 U( n4 |6 ~
+-----+------+----------------+---------+---------+------+------------+---------
7 M  s* X; `) h-----------------------------------------------------------------+1 M* h& v9 Q( ]. O( w: J
| 363 | root | localhost:1393 | history | Query   |    0 | statistics | SELECT C
7 W# o: N0 `7 U: I: }7 I) @6 iOUNT(*) FROM cdb_pms WHERE msgfromid=11212 AND folder='outbox' |  o% M: C+ i% l( V( S3 c2 T& ~
+-----+------+----------------+---------+---------+------+------------+---------' |( z7 H% j" J( ~

4 P- u- B) u9 b4 \! P  检查 cdb_pms 表的结构:
  _" R% n) V1 Fmysql> show columns from cdb_pms;
/ O' H( D" H) z0 n+-----------+------------------------+------+-----+---------+----------------+
! ^5 r" l& M- C, {9 ^| Field     | Type                   | Null | Key | Default | Extra          |
: D1 x5 f- w7 o$ X+ d+-----------+------------------------+------+-----+---------+----------------++ |2 d! n! P' f1 K3 X+ U, p! g
| pmid      | int(10) unsigned       | NO   | PRI | NULL    | auto_increment |/ W+ M: v' \9 v1 o4 ~; F5 T
| msgfrom   | varchar(15)            | NO   |     |         |                |& ?$ c/ x  s/ f- n4 e; J
| msgfromid | mediumint(8) unsigned  | NO   | MUL | 0       |                |
3 E! r9 o/ `( P3 Q( |4 \| msgtoid   | mediumint(8) unsigned  | NO   | MUL | 0       |                |" u1 g! w. j6 T" ]/ ?
| folder    | enum('inbox','outbox') | NO   |     | inbox   |                |5 u( c9 T! w* Y7 f4 m0 T
| new       | tinyint(1)             | NO   |     | 0       |                |- S/ o& }; U5 t6 B. Z: h) z
| subject   | varchar(75)            | NO   |     |         |                |
2 J) I: ~* @4 _0 z2 z7 S| dateline  | int(10) unsigned       | NO   |     | 0       |                |
& Q  s/ p8 O" ?3 Q( G| message   | text                   | NO   |     |         |                |3 k1 Y- m' ~2 Q0 Z1 g
| delstatus | tinyint(1) unsigned    | NO   |     | 0       |                |
4 ]! z8 Z2 X& l+-----------+------------------------+------+-----+---------+----------------+
8 J- ~. g5 H) R6 k/ S) X/ v- f) W10 rows in set (0.00 sec)+ L. W8 n) Y' }1 b1 @5 Z2 G

3 F% t' z5 O; L) a9 [1 I* S  这条语句: WHERE msgfromid=11212 AND folder='outbox',我们看到,在 cdb_pms 表中,msgfromid 字段已经建立了索引,但是,folder 字段并没有。目前这个表已经有记录 7823 条。显然,这会对查询造成一定影响。于是为其建立索引: $ N# T/ D/ y0 U) q8 R2 {
mysql> ALTER TABLE `cdb_pms` ADD INDEX ( `folder` );
+ I; u0 V3 Z$ j9 P( v, UQuery OK, 7823 rows affected (1.05 sec)) i. d4 l5 z4 C8 P. b6 Y0 X
Records: 7823  Duplicates: 0  Warnings: 0
, r" p6 z0 Z7 K3 n5 G, \7 [3 B+ Q& N$ p
   继续检查:
$ T" ?4 `1 P' W. `6 P( ~mysql> show processlist;
( g6 `* j% w) r# N8 E& |+------+------+----------------+---------+---------+------+------------+--------
; P  m8 t4 f$ g/ w; H! ~% p--------------------------------------------------------------------------------
% {$ f5 d! x1 {% w1 d& B) N1 f--------------+
+ Q+ G& V$ b3 R7 e3 _* G  X5 W: S| Id   | User | Host           | db      | Command | Time | State      | Info$ i# v) |% _' T% V1 ~9 _$ u
4 g  y; q- ?1 h- I5 t
              |: E8 {3 h: N, V; H' @, _/ U$ [: s1 A
+------+------+----------------+---------+---------+------+------------+--------" Z0 A' p+ b/ l6 A: F
--------------------------------------------------------------------------------
: m1 x% }- U; e/ X- W+ _% ]# }--------------+
# R: Q2 u0 f/ c/ X3 E( }' N              |9 S, `6 p3 `; U3 ]* B! l4 p' E
| 1583 | root | localhost:2616 | history | Query   |    0 | statistics | SELECT; `) N4 V# q6 }: y5 U+ V
t.tid, t.closed, f.*, ff.*  , f.fid AS fid1 |8 |# O8 p( V; G% E: C7 q
                        FROM cdb_threads t
7 d* a9 |  g+ \1 H; K! e                        INNER JOIN cdb_forums f |8 q- |, r. l! z$ M4 s" j7 ~
+------+------+----------------+---------+---------+------+------------+--------
5 B2 O$ N" V: i: D& o% y( b--------------------------------------------------------------------------------
3 }' i& |$ W0 `, {--------------+5 \7 U/ d3 S9 P! u( m! k" d
1 rows in set (0.00 sec)
- H; \' e5 @0 [2 c1 g
  n. `/ K2 o) j  这条 SQL 语句是针对最重要的数据表 cdb_threads 进行操作的,由于 show processlist 没有将这条 SQL 语句全部显示完全,经对比 Discuz 论坛的源码,此SQL语句的原型位于 common.inc.php 的 Line 283,内容如下:
. F1 A: S" l8 p9 r: F; |; Z$query = $db->query("SELECT t.tid, t.closed,".(defined('SQL_ADD_THREAD') ?
  p! ?  Z- v; o- r8 q+ Q    SQL_ADD_THREAD : '')." f.*, ff.* $accessadd1 $modadd1, f.fid AS fid' [2 p0 J* k' X5 V6 N$ |; `9 F
    FROM {$tablepre}threads t
% u0 l7 ^2 E' r    INNER JOIN {$tablepre}forums f ON f.fid=t.fid
7 r' N' ?# M  j3 o2 p: |" y3 V- A    LEFT JOIN {$tablepre}forumfields ff ON ff.fid=f.fid $accessadd2 $modadd2$ Q+ f6 ?2 y1 A  a. J
    WHERE t.tid='$tid'".($auditstatuson ? '' : " AND t.displayorder>=0")." LIMIT 1");( v6 y" N& r$ E# U$ |
7 z" o, O2 A' u" o0 x3 m9 i$ M( O4 T
   经检查,数据表 cdb_threads, 并没有针对 displayorder 字段建立索引。在 discuz 论坛中,displayorder字段多次参与了 Where 子句的比较。于是为其建立索引:
2 e, ]- y7 f$ Hmysql> ALTER TABLE `cdb_threads` ADD INDEX ( `displayorder` );
/ t3 G3 x6 F% r) f, T% K: EQuery OK, 110330 rows affected (2.36 sec)$ O0 r4 p" S  B( M2 p
Records: 110330  Duplicates: 0  Warnings: 0
- \2 S% u  Y  \, q7 Z
( T8 A4 Z- T% }8 d2 T4 x5 ^' t  此时 cpu 已经轻微下降了一部分。0 V( P) t- `! y2 f
8 ~' y/ \; M' w' U  n/ _0 n
   继续检查,发现 下面这条 discuz 的 SQL 语句,也导致负荷增加,这条语句位于 rss.php 程序中的第 142 行。 6 ~; z2 V% p% B0 P1 E, d  T
* y, t# t8 Y3 q" g
    $query = $db->query("SELECT t.tid, t.readperm, t.price, t.author, t.dateline, t.subject, p.message8 G& h; L$ B1 i  V3 p5 @$ L
    FROM {$tablepre}threads t& [6 ^6 m1 g9 M
    LEFT JOIN {$tablepre}posts p ON p.tid=t.tid AND p.first=1
, N( O; s$ T2 V  ~( f4 f6 F& {) X    WHERE t.fid='$fid' AND t.displayorder>=0
3 \( f& ~% r! h2 x9 d0 u: R# s& X    ORDER BY t.dateline DESC LIMIT $num");
+ M" s: H8 m8 l" \
8 h( G, ~: V% V# S  在这个 Order by 子句中,用到了 cdb_threads 表中的 dataline 字段。这个字段是用来存储 unixtime 的时间戳,在整个论坛程序中,大部分时候数据的排序也是基于这个字段,竟然没有建立索引。于是加上:
. O# c1 @/ b9 D6 x1 [9 Nmysql> ALTER TABLE `cdb_threads` ADD INDEX ( `dateline` );
8 I2 X, i( X% L' gQuery OK, 110330 rows affected (12.27 sec)
# E1 K4 n7 t8 aRecords: 110330  Duplicates: 0  Warnings: 0
1 ]7 R' F2 _. W( `0 U; A; W5 `% v6 w" w9 C
   查找占用 CPU 高负茶的 SQL 语句,是一件麻烦而又枯燥的事,需要一条一条排除、分析。后面的工作,都是依此类推,经过检查,共查出有八处地方,需要增加索引,如果你也碰到了 discuz 论坛导致 cpu 占用 100% 的情况,可以直接将下列语句复制过去,在 mysql 的命令行下执行即可:
* M$ `. _% d2 R1 q$ B  I; XALTER TABLE `cdb_pms` ADD INDEX ( `folder` );
7 S* n$ Q, i2 ?+ C# V6 xALTER TABLE `cdb_threads` ADD INDEX ( `displayorder` );
& @7 d) i6 k" R/ \ALTER TABLE `cdb_threads` ADD INDEX ( `dateline` );2 S3 ]: [( K0 V2 a  q
ALTER TABLE `cdb_threads` ADD INDEX ( `closed` );9 X, |9 t) M5 q: B* A9 W
ALTER TABLE `cdb_threadsmod` ADD INDEX ( `dateline` );7 S2 R- o7 K/ `6 y* `& A
ALTER TABLE `cdb_sessions` ADD INDEX ( `invisible` );4 p- @( m. Y% O8 T. L7 T% V
ALTER TABLE `cdb_forums` ADD INDEX ( `type` );
1 A' }% w9 b# A0 OALTER TABLE `cdb_forums` ADD INDEX ( `displayorder` );$ f" E4 m' e9 ]2 u) ^& k

" n& q( \  \* H: t  注意:“cdb_” 是 discuz 论坛的默认数据表前缀。如果你的表名前缀不是 “cdb_”,则应该改成你对应的表名。例如:my_threads, my_pms 等等。
# Z& g9 N+ o6 R, B% s) e
; i' Q9 m* {3 b$ @! }" k
+ D1 N0 Q; c6 v5 {  完成这些结构的优化之后,整个系统的 CPU 负荷在 10%~20%左右震荡,问题解决。
' X6 J2 N) X8 f0 S9 u1 f- A; t! Z( U) u2 a% u# J6 C6 e( V% p
& u* O5 U, n! [9 H) |
   我很奇怪,设计数据库结构,是一个数据库开发人员的基本功,discuz 论坛好歹也是一个发展了有六七年的论坛了,为何数据库结构设计得如此糟糕?我想也许有如下三个原因:
$ c+ m5 [5 l- ]+ }
7 o6 ~8 D2 Z/ E) c' }; B* s! ^1 T, E' A
数据库开发人员设计时本身的疏忽 ) ?1 n0 |; r/ K3 N5 _5 O
故意留下的缺陷,当普通论坛没有上数量级的记录时,不会感觉到这个问题,当数据量增大(例如千万级),此问题突现,以便针对用户提供个性服务收取服务费.呵呵,估且以最大的恶意来猜测此事,玩笑而已,不必当真。  4 \  R; [: I1 h
另一个可能就是用户的论坛是从低版本升级而来,程序升了级,但数据结构也许没有做相应的更新
+ B$ |6 f# r' r, K
0 w/ N* r! B" M$ f( I
4 y2 F8 T( m) i4 y# N# N/ i. h  G& \8 P8 c: ?  U
8 j4 `( F5 ~! c5 v. |  |" s
   今天查看网站日志的 reffer, 发现在 discuz 的官方论坛上,有人就此文引起了一些争论: http://www.discuz.net/thread-673887-1-1.html。discuz 的管理员和管理员有如下言论: + B3 v9 X2 G& p0 U/ d
; a5 u: k0 W+ [4 W) `5 v8 Y2 @. I
引用自 cnteacher:
1 q* S+ ~% A+ ?  ~7 l- E
# }- Q/ W- c. M' x/ f" i恰恰相反,discuz 的优化措施和数据库的索引是按照大规模论坛设计的。
# E" F; Y5 |. g5 i
  K# l, w$ l+ X  ]0 N, [  OTO 一楼:数据库结构的设计都是按照程序应用来进行的,使用任何非Discuz! 标准版本以外的代码和程序,或者变更标准数据结构,均可能遇到不可预知的各种问题。 ' z/ E& ~2 k# w, w/ \/ \. J2 U( }' G
5 M5 P0 v  Q9 ]
引用自 童虎:
' ~9 N$ g) b' W+ V# G0 ?
% j+ u% t; H2 ^1 O; V* h你们可以看看xxxxx, xxxx之类的比较大型的网站,这种网站使用dz论坛都没有问题,说明dz标准程序是没有问题,出现楼主说的情况,多半属于服务器或者安装一些插件造成的
5 @$ T6 F* K( K( U; H% m; J( n* `. b6 \: Z4 b" Y2 C# s; {
   显然将问题推给插件的原因是不正确的.举个简单的例子:在最新的 discuz 5.5.0 forumdisplay.php 第183 行,有如下语句:
) A+ F' v* G7 _# U5 B; ^! P
2 C# Z! R% p1 F/ R* l$query = $db->query("SELECT uid, groupid, username, invisible,
; c/ ]4 G# M0 n4 m- R* H% U# A8 @  lastactivity, action FROM {$tablepre}sessions
8 c' N7 P1 J& _  WHERE $guestwhere fid='$fid' AND invisible=0");) Y; {' {# W% J8 P. [" Z7 u

9 p6 m. F1 y2 H3 C, q- W( d  这里的 invisible 并没有建立索引。本文中有评论认为 session 表是内存表, 速度会很快。理论是如此。不过我在 show processlist 中,观察到上面这条语句占用了大量 CPU, 所以也将其一并加上了 index。cdb_threads 中的 closed 等字段, 也多次参与 where 运算, 也没有建立索引。这些运算的语句, 是 discuz 自己的程序中的。!


  自从这篇笔记发表以来,在我的这篇文章的评论、以及我的联系消息中,就经常收到许多下面两种类型的评论和邮件:一、许多技术人员批评我胡说八道、Dizcus 论坛不需要做优化或者不能乱建索引的;二、许多使用Dizcus 的站长找我“冰天雪地luo体跪求”解决他们的 CPU 占用 100% 的问题。
( T3 S0 u; I" Y4 R8 Z& I' P2 S
0 t7 ?2 |; a& \/ O  关于 MySQL 数据库优化技术上的争论,我的观点再次声明如下:
. o1 _% q8 H9 v. N
# s% ^1 A3 Z; b* ~8 _
1 j1 e& o# J2 d( [" z$ ^; _- c技术上的争论是可以放开了讨论的。而我的水平也确实只是半瓶子水,对数据库的理论知识也只懂这么点,牛牛们的批评,我虚心接受,非常感谢。但是,评论里的批评不要上升到人身攻击,否则,我的地盘我作主,直接删除。我喜欢听好话,请大家理解一个三○男人的这点可怜的虚荣心。 8 S, j5 r# Y0 C3 F& l  v8 x
; U% {6 [$ F+ v# \" U" Y$ h

3 j% a7 r$ j* u$ e4 i数据库的优化,要涉及到的方方面面很多。关说理论是没有用的,得靠事实说话。一个千万级数据库的实例优化说明不了问题,两个千万级的数据库优化也许还说明不了问题,但我相信,三个、四个、五个总是可以说明问题的,--截止到 2007.11.09,我已经帮助朋友优化过五个记录数超过 1000 万的 discuz 论坛了。优化之前,cpu 都是 100%;优化之后,cpu 降到 30%~40% 左右。我想事实胜于雄辩。 # L. J9 ^* x4 @' Z

/ s% N5 e1 z3 U0 P  关于找我帮忙解决数据库优化的评论和邮件,答复如下: 1 L( z: H- Y. o$ p, y/ [
+ `& [$ W% d; m( m- {% }) b/ i/ X; w0 z
$ H8 f$ F# h" B* u6 j7 w
数据库的优化,不同的版本有不同的实际情况,优化一个 database,短则三两小时,慢则半天一天。请大家理解一个三○老男人养家的压力,我的精力有限,不可能一一帮到。
/ B7 Z9 m' a" T. s
0 n0 ?% t3 e$ U! o: ]1 ^! h$ ?. [% z' s+ a' Z
对于个人网站,我可以在周六周日的空余时间内帮忙。请事先与我联系好。
6 C- b: q1 a# u0 n
3 ?+ E; R, L0 F8 R* z) S
1 T$ V) s! L/ y, \# P1 a- F0 t+ G( ~  z
关于装有首页四格插件的 dz 论坛导致 MySQL 占用 大量CPU 的分析0 W7 M1 v# q& `# \$ t8 Y( f4 V
  某一朋友的基于 Discuz 的论坛,也存在 CPU 占用 100% 的问题,服务器从 Win 2003 换到 CentOS,内存 2G, CPU 1.86G, 数据:cdb_threads 4 万,cdb_posts 96 万,cdb_members 35 万,已经按我上面文章所说的优化过索引。按说这个配置足够运行论坛了,但问题一直得不到解决。
1 S% @: q+ y7 c0 x: m. i6 ~5 ]( w6 }* X% F" \
  经过调试,将慢查询的结果 dump 到 /usr/local/mysql/var/localhost-slow.log,运行 /usr/local/mysql/bin/mysqldumpslow /usr/local/mysql/var/localhost-slow.log 查看,结合 show processlist 命令,发现慢查询集中在下列语句: $ R" E4 q: x/ u% K7 {
+ A1 Y. r# ]9 L! [  I5 L% t1 H9 V; E
SELECT t.*, f.name FROM cdb_threads t, cdb_forums f WHERE   ~! D& P; q! v7 t% ]
t.fid<>'S' 1 {$ E- ]- y3 a
AND f.fid=t.fid
  ~5 `. v/ |, VAND f.fid NOT IN (N,N,N,N)
) d; v5 P' c% D9 xAND t.closed NOT LIKE 'S'
/ i: N% D- Z1 J& ]AND t.replies !=N + s% x" ^& p) g, _6 ^: X7 b
AND t.displayorder>=N . B; q( }4 Z: |1 G/ m5 j
ORDER BY t.views DESC LIMIT N, N1 M* `9 h' c9 \* P/ P% b5 v2 V
  然而搜索 Dizcus 论坛的源码,并没有找到这行代码。怀疑是插件的原因。经查,论坛装了首页四格的插件,这行语句位于 include/toplist.php 中: 仔细检查这行代码,发现存在许多性能或语法规范上的问题:# P5 @0 B" i& T: B
; Z' y9 u! |" T

# i) u" d  Y6 q; X- `AND t.closed NOT LIKE 'S':t.closed 是数值字段,不应该用 LIKE 'S' 的形式参与比较。 
/ {" j5 O( e1 `, zORDER BY t.views: t.views 在 dizcus 的原始数据表中,是没有做索引的。 8 h, p$ X, @5 }
SELECT t.*: 这种写法,是不被推荐的。如果要选择某个表内的所有字段,最好是按实全部写出来,例如:select t.aa, t.bb, t.cc, t.dd, ...
* p' x! f3 d. W7 e7 h- GWHERE t.fid <> 'S': t.fid 是数值型字段,不应该写成 字符比较的形式。这个对性能影响不大,是个编程规范的问题。
! p, Q! A; v7 y. j....
: T4 P- A9 B0 W6 k$ m9 t9 T) {. X7 L0 W# _
  toplist.php 的其他三条 sql 语句,都存在这些问题。如果要针对他的 sql 语句去优化 MySQL 结构,会带来不良的后果;如果直接改他的 toplist.php 程序,如果站长以后升级 toplist.php 又怕带来不兼容问题。于是我建议他干脆关闭首页四格插件。
+ Q; f' f! R9 |. }' ?7 D- V" b+ y  ]9 S, W  l2 z) @9 r" v
  关闭首页四格插件之后,CPU 降到 18% 左右震荡,表现非常良好。
# l  ?! O9 T2 H# U. a+ \" @
( u$ P1 p+ P, }$ n2 r  如果是我来写首页四格的程序,我不会采用这种方案,我会用定时15分钟或30分钟查询一次数据库,将结果写入 TXT 文件或临时表,然后程序再从中读取,效率会高许多。% ?1 f4 X) e( e# `2 b1 o
7 G$ a& J. A% \7 k7 i
  结论:2 e' d5 A' Y4 W. L/ Z  B6 P4 l

1 m4 i0 X& Q4 P, F1 s  J$ w- p如果装了插件的论坛碰到 CPU 高负荷时,建议关掉插件再评估性能。
: E1 h3 }) g- b3 C" Q1 d慎装第三方插件。没事不要乱插。
]]>
微软今起黑屏警示盗版 你黑屏了吗? http://www.rzzone.net/docdetail.php?id=191 中国启动Windows XP和Office的正版验证行动,盗版用户的电脑将每小时黑屏1次,并会不断弹出提示窗口提醒正在使用盗版软件。

微软预计在一个半月内通知到所有XP专业版操作系统用户。微软强调,上述计划的目的“是让大家知道自己使用的是不是正版”,是“善意的提醒”,用户也可以很方便地通过上述提醒进入到一个专门页面购买正版操作系统。不过,微软没有透露相关的可能的销售预期,并表示,此次计划与“和市场份额无关”,及这一策略乃全球行动,并非针对中国市场。

用户可不参与正版验证计划 不起诉盗版用户

但微软也表示,用户可以选择不参与上述计划,并且其正常使用和升级不会受到任何影响。如果用户不愿意参与该计划,只需在接到微软WGA和OGA下载更新提示时,不主动进行更新。但微软并不鼓励用户这么做,因为“盗版蕴含了巨大的使用风险”。这些风险包括了遭受病毒攻击、木马程序等的威胁。

10月16日,微软公司全球副总裁、微软大中华区代理CEO张亚勤在接受媒体采访时说:“我们这么做,不是为了釜底抽薪打盗版,只是为了帮助用户识别自己电脑中的软件是不是正版,以选择购买正版软件,或者采取其他措施。”

对此,张亚勤16日表示,用户可以通过卸载有关组件来免受电脑黑屏的干扰。“同时,微软不会用自己拥有的正版预装数据对盗版软件用户企业提起诉讼。”

多数网友表示反对

不过,微软的这一举措立刻遭到了广大网友的反对,在腾讯科技推出的调查显示,截止发稿时,已有近20万网友投票反对微软的该项计划。

中国工程院院士倪光南对此评论称,微软可以在用户不知情的情况下从用户机器中提取某些信息,可以发出黑屏等等警告,如果需要的话,也可以干脆叫它死机。所以,不是自主可控的软件就不可能保障信息安全。总之,最好的应对是大力推进基于国产软件的正版化。

微软上周发出将黑屏提醒盗版用户的消息后,立刻引发了多种连锁反应,如:金山率先提出,WPS办公软件已经与Office深度兼容,并祭起免费大旗抢夺微软Office用户;一些地区的网吧为保证用户不受到黑屏骚扰,开始安装正版操作系统,致使当地正版Windows XP的销量上升五成;最有意思的当属微软对此作出的反应,微软产品部门相关负责人jim lin通过媒体向广大用户透露“防黑屏”的高招,他表示,用户只需卸载系统内帮助识别是否正版的组件,将不再受电脑黑屏与警示标识的干扰。]]>
smarty的html_select_date http://www.rzzone.net/docdetail.php?id=190

   <li>{html_select_date}</li>
   <li>{html_select_date display_years=false display_days=false month_format='%m'}</li>
   <li>{html_select_date start_year='-5' end_year='+1' display_days=false}</li>
   <li>{html_select_date start_year='1950' end_year='2000' year_as_text=yes display_days=false}</li>
   <li>{html_select_date start_year="-80" month_format="%m" field_order="YMD" reverse_years="yes"}</li>
   <li>{html_select_date field_order="YMD" year_as_text="true" month_format="%m" day_value_format="%02d" field_separator="&nbsp;&nbsp;&nbsp;&nbsp;" }</li><br>
   <li>{html_select_time use_24_hours=true}</li>

smarty之html_select_date

属性 类型 是否必须 缺省值 描述
prefix string No Date_ 变量名称前缀
time timestamp/YYYY-MM-DD No UNIX时间戳或年-月-日 使用时间类型(data/time)
start_year string No 年份或与当前年份的相对值 下拉列表中第一个年份,或与当前年份的相对值(正/负 几年)
end_year string No 同start_year 下拉列表中最后一个年份,或与当前年份的相对值(正/负 几年)
display_days boolean No true 是否显示天
display_months boolean No true 是否显示月
display_years boolean No true 是否显示年
month_format string No %B 月份的表示方法(strftime)
day_format string No %02d 天显示的格式(sprintf)
day_value_format string No %d 天的表示方法(sprintf)
year_as_text boolean No false 是否以文本方式显示年份
reverse_years boolean No false 逆序显示年份
field_array string No null 如果指定了名称,选定的区域将以[Day],[Year],[Month]的形式返回给PHP(待考)
day_size string No null 如果给定,为标签添加大小属性
month_size string No null 如果给定,为标签添加大小属性
year_size string No null 如果给定,为标签添加大小属性
all_extra string No null 如果给定,为所有标签添加附加属性
day_extra string No null 如果给定,为标签添加附加属性
month_extra string No null 如果给定,为标签添加附加属性
year_extra string No null 如果给定,为标签添加附加属性
field_order string No MDY 显示区域的顺序
field_separator string No \n 各区域间输出的分隔字符串
month_value_format string No %m 月份值的strftime表示方法,默认为 %m

]]>
基本正则式例 http://www.rzzone.net/docdetail.php?id=189 整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$
只能输入数字:"^[0-9]*$"。
只能输入n位的数字:"^\d{n}$"。
只能输入至少n位的数字:"^\d{n,}$"。
只能输入m~n位的数字:。"^\d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
只能输入非零的负整数:"^\-[1-9][]0-9"*$。
只能输入长度为3的字符:"^.{3}$"。
只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。
验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。
只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。
验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。

string input="A sailor went to sea to sea,"+"to see what he could see could see. ses";
    Regex reg=new Regex("se.");
    Match matchmade=reg.Match(input,20);
    while(matchmade.Success)
    {
     Response.Write(matchmade.Value+"<br>");
     matchmade=matchmade.NextMatch();
    }
\d 可匹配任何数字
\D 匹配任何非数字
\w 任一单词 a-z A-Z 0-9 _
\W 非单词字符 比如 @#$%^&*
\s 任一空白字符包括制表符,换行符 回车符 换页符
\S 任一非空字符
.   匹配任一字符 换行符除外
[] 匹配括号内任一字符
[^] 匹配括号内任一字符

\A   前面的模式必须在字符串的开始处,多行标志被忽略
\z   前面的模式必须在字符串的末尾处,多行标志被忽略
\Z   前面的模式必须在字符串的末尾处,或位于换行符前
\b   匹配单词边界实质上是单词字符和非单词字符间的点,单词字符[a-zA-Z0-9]的任一字符位于一个单词的开始
\B   匹配一个非单词边界位置不在一个单词的开始
{n}
{n,}
{n,m}
? 匹配0或1
+ 匹配至少1次
* 匹配0次或多次


\n 匹配换行
\r 匹配回车
\t 匹配tab
\v 匹配垂直制表符
\f 匹配换页符
\nnn    匹配一个三位8禁制ascII字符   例如\103 匹配C
\xnn    匹配一个二为16禁制ascII字符 例如\x43 匹配C
\unnnn 匹配一个四位16进制unicode字符
\cV 匹配一个Ctr-V

]]>
仿土豆视频滚动菜单 http://www.rzzone.net/docdetail.php?id=188 效果测试


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<style>
ul{margin:0;padding:0;list-style:none;width:100000px}
li{margin:0;padding:0;width:100px;height:100px;display:block;float:left;margin-right:5px;background:#009900}
#img_bag{width:640px;height:100px;background:#FF9900;margin:0 auto;}
#img_bag a{float:left;width:20px;display:block;height:20px;font-weight:bold;}
#img_bag #img{width:600px;height:100px;background:#ccc;overflow:hidden;float:left}
#scrollBar{width:600px;height:20px;background:#FF0000;margin:0 auto;position:relative}
#scroll{width:30px;height:20px;background:#000;cursor:pointer;position:absolute;}
</style>
</head>
<body>
<div id="img_bag">
<a href="javascript:void(0)" onmousedown="moveLeft()">&lt;&lt;</a>
<div id="img">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<a href="javascript:void(0)" onmousedown="moveRight()">&gt;&gt;</a>
</div>
<div style="clear:both;"></div>
<div id="scrollBar">
<div id="scroll" style="left:0"></div>
</div>
<script>
function $(obj){return document.getElementById(obj)}
var maxWidth=$("img").getElementsByTagName("ul")[0].getElementsByTagName("li").length*105;
var isScroll=false;
var modiLeft;
$("scroll").onmousedown=function(evt){
isScroll=true;
evt=(evt)?evt:((window.event)?window.event:null);
if(evt.offsetX){
modiLeft=parseInt(evt.offsetX)
}
else{modiLeft=parseInt(evt.layerX)}
}
document.onmouseup=function(){
isScroll=false;
}
document.onmousemove=function(evt){
evt=(evt)?evt:((window.event)?window.event:null);
if(evt&&isScroll){
$("scroll").style.left=parseInt(evt.clientX)-parseInt($("scrollBar").offsetLeft)-modiLeft+"px";
if(parseInt($("scroll").style.left)<0){$("scroll").style.left=0+"px"}
if(parseInt($("scroll").style.left)>570){$("scroll").style.left=570+"px"}
$("img").scrollLeft=parseInt($("scroll").style.left)*((maxWidth-600)/570);
  }
}
var targetx = 200;//一次滚动距离
var dx;
var a=null;
function moveLeft(){
var le=parseInt($("img").scrollLeft);
if(le>200){
targetx=parseInt($("img").scrollLeft)-200;
}
else{targetx=parseInt($("img").scrollLeft)-le-1}
scLeft();
}
function scLeft(){
dx=parseInt($("img").scrollLeft)-targetx;
$("img").scrollLeft-=dx*.3;
$("scroll").style.left=parseInt($("img").scrollLeft)*(570/(maxWidth-600))+"px";
if(parseInt($("scroll").style.left)<0){$("scroll").style.left=0+"px"}
if(parseInt($("scroll").style.left)>570){$("scroll").style.left=570+"px"}
clearScroll=setTimeout(scLeft,50);
if(dx*.3<1){clearTimeout(clearScroll)}
}
function moveRight(){
var le=parseInt($("img").scrollLeft)+200;
var maxL=maxWidth-600;
if(le<maxL){
targetx=parseInt($("img").scrollLeft)+200;
}
else{targetx=maxL}
scRight();
}
function scRight(){
dx=targetx-parseInt($("img").scrollLeft);
$("img").scrollLeft+=dx*.3;
$("scroll").style.left=parseInt($("img").scrollLeft)*(573/(maxWidth-600))+"px";
if(parseInt($("scroll").style.left)<0){$("scroll").style.left=0+"px"}
if(parseInt($("scroll").style.left)>=570){$("scroll").style.left=570+"px"}
a=setTimeout(scRight,50);
if(dx*.3<1){clearTimeout(a)}
}
</script>
</body>
</html>]]>
使用window.name解决跨域问题[2] http://www.rzzone.net/docdetail.php?id=187 Web 服务器如何提供 window.name 数据

为了让 Web 服务器实现 window.name,服务器应该只寻找请求中是否包含 windowname 参数。如果包含了 windowname 参数,服务器应该返回一个设置了 window.name 字符串值的 HTML 文档,回应此请求并传送到客户端。例如:
http://www.planabc.net/getdata.html?windowname=true

如果服务器想用 Hello 响应客服端,它应该返回一个 HTML 页面:

<html>
    <script type="text/javascript">
        window.name="Hello";
    </script>
</html>

同样也可以转换为 JSON 数据:

<html>
    <script type="text/javascript">
        window.name='{"foo":"bar"}';
    </script>
</html>

如果你手动创建资源,书写大量的多行的 JSON 对象为一个引用的字符串应该是比较困难的并且易于出错的。可以使用这样的 HTML 样例简单的创建 JSON 数据,将会转换为一个 JSON 字符串而无需手动转义 JSON 为字符串:

<html>
    <script type="\'text/javascript\'">
        window.name = document.getElementsByTagName("script")[0].innerHTML.match(/temp\s*=([\w\W]*)/)[1];
        temp= {
            foo:"bar", // put json data here
            baz:"foo"
        }
    </script>
</html>

同样的,如果你想传递 HTML/XML 数据,这里有一个样例实现,而无需手动将这些数据转换成字符串:

<html>
    <body>
        <p id="content">
            some <strong>html/xml-style</strong>data
        </p>
    </body>
    <script type="text/javascript">
        window.name = document.getElementById("content").innerHTML;
    </script>
</html>

window.name 传输技术相比其他的跨域传输的一些优势:

  1. 它是安全的。也就是说,它和其他的基于安全传输的 frame 一样安全,例如 Fragment Identifier messaging (FIM)和 Subspace。(I)Frames 也有他们自己的安全问题,由于 frame 可以改变其他 frame 的 location,但是这个是非常不同的安全溢出,通常不太严重。
  2. 它比 FIM 更快,因为它不用处理小数据包大小的 Fragment Identifier ,并且它不会有更多的 IE 上的“机关枪”声音效果。它也比 Subspace 快,Subspace 需要加载两个 Iframe 和两个本地的 HTML 文件来处理一个请求。window.name 仅需要一个 Iframe 和一个本地文件。
  3. 它比 FIM 和 Subspace 更简单和安全。FIM 稍微复杂,而 Subspace 非常复杂。Subspace 也有一些额外的限制和安装要求,如预先声明所有的目标主机和拥有针对若干不同特殊主机的 DNS 入口。window.name 非常简单和容易使用。
  4. 它不需要任何插件(比如 Flash)或者替代技术(例如 Java)。
]]>
使用window.name解决跨域问题[1] http://www.rzzone.net/docdetail.php?id=186 window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制、数据只能是字符串、设置和获取 cookie 语法的复杂等等)而发明的(详细见原文:《Session variables without cookies》),后来 Kris Zyp 在此方法的基础上强化了 window.name 传输 ,并引入到了 Dojo dojox.io.windowName),用来解决跨域数据传输问题。

window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

window.name 传输技术的基本原理和步骤为:

name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。同源策略依旧防止其他 frame 访问 name 属性。一旦 name 属性获得,销毁 frame 。

在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性。

基本实现代码,基于 YUI,源自 克军写的样例

(function(){
    var YUD = YAHOO.util.Dom, YUE = YAHOO.util.Event;

    dataRequest = {
        _doc: document,
        cfg: {
            proxyUrl: 'proxy.html'
        }
    };

    dataRequest.send = function(sUrl, fnCallBack){
        if(!sUrl || typeof sUrl !== 'string'){
            return;
        }

        sUrl += (sUrl.indexOf('?') > 0 ? '&' : '?') + 'windowname=true';

        var frame = this._doc.createElement('iframe'), state = 0, self = this;
        this._doc.body.appendChild(frame);
        frame.style.display = 'none';

        var clear = function(){
            try{
                frame.contentWindow.document.write('');
                frame.contentWindow.close();
                self._doc.body.removeChild(frame);
            }catch(e){}
        };

        var getData = function(){
            try{
                var da = frame.contentWindow.name;
            }catch(e){}
            clear();
            if(fnCallBack && typeof fnCallBack === 'function'){
                fnCallBack(da);
            }
        };

        YUE.on(frame, 'load', function(){
            if(state === 1){
                getData();
            } else if(state === 0){
                state = 1;
                frame.contentWindow.location = self.cfg.proxyUrl;
            }
        });

        frame.src = sUrl;
    };
})();

]]>
解决网站大流量问题的策略 http://www.rzzone.net/docdetail.php?id=185 博客由于访问量过大而引起服务器性能问题,这是很多人的烦恼,有人使用取消RSS的方法来解决问题,显然是下错药,那么对于网站大流量带来的问题,正确的解决方法应该是什么呢?下面是我个人总结的一些经验,供大家参考。

  首先,确认服务器硬件是否足够支持当前的流量。

  普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大,那么必须首先配置一台更高性能的专用服务器才能解决问题,否则怎么优化都不可能彻底解决性能问题。

  其次,优化数据库访问。

  前台实现完全的静态化当然最好,可以完全不用访问数据库,不过对于频繁更新的网站,静态化往往不能满足某些功能。

  缓存技术就是另一个解决方案,就是将动态数据存储到缓存文件中,动态网页直接调用这些文件,而不必再访问数据库,WordPress和Z-Blog都大量使用这种缓存技术。我自己也写过一个Z-Blog的计数器插件,也是基于这样的原理。

  如果确实无法避免对数据库的访问,那么可以尝试优化数据库的查询SQL.避免使用Select * from这样的语句,每次查询只返回自己需要的结果,避免短时间内的大量SQL查询。

  第三,禁止外部的盗链。

  外部网站的图片或者文件盗链往往会带来大量的负载压力,因此应该严格限制外部对于自身的图片或者文件盗链,好在目前可以简单地通过refer来控制盗链,Apache自己就可以通过配置来禁止盗链,IIS也有一些第三方的ISAPI可以实现同样的功能。当然,伪造refer也可以通过代码来实现盗链,不过目前蓄意伪造refer盗链的还不多,可以先不去考虑,或者使用非技术手段来解决,比如在图片上增加水印。

  第四,控制大文件的下载。

  大文件的下载会占用很大的流量,并且对于非SCSI硬盘来说,大量文件下载会消耗CPU,使得网站响应能力下降。因此,尽量不要提供超过2M的大文件下载,如果需要提供,建议将大文件放在另外一台服务器上。

  第五,使用不同主机分流主要流量

  将文件放在不同的主机上,提供不同的镜像供用户下载。比如如果觉得RSS文件占用流量大,那么使用FeedBurner或者FeedSky等服务将RSS输出放在其他主机上,这样别人访问的流量压力就大多集中在FeedBurner的主机上,RSS就不占用太多资源了。

  第六,使用流量分析统计软件

  在网站上安装一个流量分析统计软件,可以即时知道哪些地方耗费了大量流量,哪些页面需要再进行优化,因此,解决流量问题还需要进行精确的统计分析才可以。

]]>