IIS下配置PHP

一、安装php

1) 在D盘新建一个名为PHP的文件夹,解压缩php的zip压缩包到D:\PHP(根据自己的习惯即可,但最好不要放到program files目录下,因为此目录包含空格,可能会产生未知问题)。

2) 在D:\PHP文件夹下找到php.ini-development文件(如果服务器不是为了开发调试用,则找到php.ini-production),将其复制一份以做备份。将复制后的文件更名为php.ini。

3) 在php.ini文件中找到以下行:extension_dir = “ext”(注:该行指定PHP查找扩展的位置),编辑该行,如下所示:

extension_dir = “D:/PHP/ext”(注:不要这里用的是斜杠/而不是反斜杠\)。

4) 在php.ini文件中找到以下行:;extension=php_mysql.dll(注:该行开始的分号指示PHP忽略该行),删除该行始的分号以启用扩展

自己根据需要将需要的扩展启用,一般还有mbstring、mysqli、gd2、pdo等。

PHP安装目录下的php.ini-development 并改名为php.ini 文件。

5) 在php.ini 文件中找到如下内容:

[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezo…
; date.timezone = 本文来自www.iisboy.com

更改为

[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezo…
date.timezone = Asia/Shanghai

如果不改以上的date.timezone可能打开网页会提示500错误,还要注意上面最后一行前的分号要去掉。

5) 保存并关闭php.ini文件。

至此,PHP安装完毕。

二、IIS中的配置

1) 下载并安装 FastCGI Extension for IIS 6.0 and 5.1,下载地址:http://www.iisboy.com/iis_down/552.html

2) 打开IIS管理器,在要支持php文件的网站上点右键 — 属性 — 主目录 — 配置 — 添加,配置方法如下图

上图中可执行文件地址为:C:\WINDOWS\system32\inetsrv\fcgiext.dll

3) 打开FASTCGI 配置文件 C:\WINDOWS\system32\inetsrv\fcgiext.ini,在最后 [Types] 修改为这样的样式

[Types]
php=PHP
[PHP]
ExePath=D:\php\php-cgi.exe

至此,配置完毕。

三、可能出现的错误

《fastcgi error 14001错误原因与解决办法》

 

MySQL中decimal类型的一点注意

MySQL中的decimal可以存储小数,经常用于价格、金额等的存储。

但建表时需指定decimal的格式,例如 decimal(5,2)或decimal(4,1)等等。

那么decimal(5,2)或decimal(4,1)代表什么意思呢?

笔者今天刚刚发现自己一直以来的一个错误:一直认为decimal(5,2)表示的是小数点前可存5位,小数点后可存2位。

但今天一个客户在充值后,我发现账户余额显示为999.99元。

后来经调试才发现,decimal(5,2)其实表示的是总共有5位,小数点后可存2位。这样也就是小数点前只能存3位。

如果插入的数值大于1000,那么都将存储为999.99。

希望同样存在此错误认识的朋友能看到这篇文章。以免造成损失。

对于编程实现心态的一点感悟

Be open minded in programming!

勇于尝试那些你不熟悉但正确的实现方法。

比如,模板机制,异常,存储过程,命令行模式使用数据库。

用你当前所能想到的最佳方式去实现。

如果你一直停留在使用自己所熟知但并不是最佳的方法,那么就很难进步。

不断运用那些非常好用但不熟悉的方法,直到它也变成你的习惯。这时你就又迈入了一个新的层次。

网站运行原理的理解

第一步:用户输入网址并点击Go后,浏览器就会将网址中的域名发送到电脑网络设置中指定的DNS服务器,然后该DNS服务器返回解析后的IP地址。

第二步:浏览器得到要访问网站的服务器IP地址后,就会访问该服务器IP的80端口建立socket连接,并通过socket的send()方法将用户输入的网址发送给服务器。浏览器就相当于一个SOCKET网络程序的客户端Client程序。

第三步:服务器端一直运行着一个监听80端口的软件,这个服务器软件一般称为WebServer。(WebServer的本质:就是在服务器电脑上一直运行着的一个SOCKET网络程序的Server端,一直监听80端口。)这样WebServer通过socket的recv()方法得到用户浏览器send过来的网址。

第四步:如果用户输入的网址类似http://www.renrenstudy.com,这里在域名后没有输入某个具体页面,这样服务器就会按照服务器设置的默认文档顺序来寻找默认文档返回给用户,一般的默认文档就是index.html,index.asp,index.jsp,index.aspx,index.php,default.html,default.asp……。如果域名后加了具体某个页面的地址,例如http://www.renrenstudy.com/news.html,那么服务器就会去寻找网站根目录下是否有news.html文件,如果有则将文件内容返回给用户,也就是用户的浏览器。

第五步:浏览器对返回的html文件内容进行HTML语言解释,展示出网页。

为了便于说明,上面的五个步骤仅仅说明的是对网站静态页面的访问,也就是直接访问.html格式的文件。其实,网站动态页面更常见,也就是网址的后缀是.php, .asp, .aspx, .jsp等的页面。

php asp jsp aspx的出现原因:html文件只是个静态的文件,不能实时更新内容。这时候就需要一个能连接数据库的程序来动态生成html文件。

php asp jsp aspx在服务器端的本质:都可以看成一个编译或解释程序。

WebServer收到的网址如果是“news.php”、“news.aspx”、“news.asp”、“news.jsp”等动态页面,那么WebServer就会将这些页面的扩展名发送给相应的程序。news.php发送给php处理程序,news.jsp发送给jsp处理程序,这些处理程序和页面扩展名的对应关系是在WebServer中可配置的。处理程序根据具体页面的名称找到对应的文件,并将其中的代码进行解释,然后这些程序就会将解释后的内容生成一个HTML文件,然后交给WebServer,由WebServer再返回给浏览器。

本文章原创自人人学习网,转载请注明出处。

缩略图无法显示_timthumb.php中的路径问题_Broadside_cn 1.0_ProgressionStudios_汉化:唯艾迪 weidea.net

用了一个wordpress主题:Broadside_cn 1.0,作者为 ProgressionStudios,汉化:唯艾迪 weidea.net。结果出现图片无法显示的问题。出现很多警告,如下取第一条警告。

Warning: file_exists() [function.file-exists]: open_basedir restriction in effect. File(/usr/local/apache2/htdocs/wp-content/themes/Broadside_cn/images/backgrounds/blog-background.jpg) is not within the allowed path(s): (/webhome:/tmp) in /webhome/********/web/www/wp-content/themes/Broadside_cn/timthumb.php on line 902

从警告中我们就可以猜测出是文件路径的问题。应该是找不到指定的图片。下面给出解决办法,希望能帮到同样碰到此问题的童鞋。

找到该主题所在目录下的timthumb.php文件,打开后找到函数getLocalImagePath($src),找到函数中的下面这段:

[php]
if(file_exists ($this->docRoot . ‘/’ . $src)) {
$this->debug(3, “Found file as ” . $this->docRoot . ‘/’ . $src);
$real = $this->realpath($this->docRoot . ‘/’ . $src);
if(stripos($real, $this->docRoot) === 0){
return $real;
} else {
$this->debug(1, “Security block: The file specified occurs outside the document root.”);
//allow search to continue
}
}
[/php]

修改成下面的代码:

[php]
if(@file_exists ($this->docRoot . ‘/’ . $src)) {
$this->debug(3, “Found file as ” . $this->docRoot . ‘/’ . $src);
$real = $this->realpath($this->docRoot . ‘/’ . $src);
if(stripos($real, $this->docRoot) === 0){
return $real;
} else {
$this->debug(1, “Security block: The file specified occurs outside the document root.”);
//allow search to continue
}
} else {
$this->docRoot = str_replace(dirname($_SERVER[‘PHP_SELF’]),””,dirname(__FILE__));
}
[/php]

如果还是有问题,可以在下方评论中提出,或者通过QQ联系我363165133,希望能帮到大家。

defaultlib “msvcrt.lib” conflicts with use of other libs

解决办法:

VC6.0版本:project->setting->link,在“工程选项”的最后添上:/NODEFAULTLIB:msvcrt.lib

其他版本:project->setting->link-> Category(input)-> Ignore   libraries里面添加上msvcrt.lib

 

解释:

1、msvcrt.lib   ——   MicroSoft Visual C RunTime(我是这么理解的)

详见百度百科:http://baike.baidu.com/view/665378.htm

2、这个警告:defaultlib “msvcrt.lib” conflicts with use of other libs

msvcrt.lib是个默认库,此库使用的其他库产生了冲突。

具体详见:http://www.cnblogs.com/bpbp/archive/2011/07/13/2104816.html

 

MySQL性能优化的最佳20+条经验(转载)

今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显。关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情。当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能。这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库。希望下面的这些优化技巧对你有用。

1. 为查询缓存优化你的查询

大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了。

这里最主要的问题是,对于程序员来说,这个事情是很容易被忽略的。因为,我们某些查询语句会让MySQL不使用缓存。请看下面的示例:

1
2
3
4
5
6
// 查询缓存不开启
$r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()");
// 开启查询缓存
$today = date("Y-m-d");
$r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");

上面两条SQL语句的差别就是 CURDATE() ,MySQL的查询缓存对这个函数不起作用。所以,像 NOW() 和 RAND() 或是其它的诸如此类的SQL函数都不会开启查询缓存,因为这些函数的返回是会不定的易变的。所以,你所需要的就是用一个变量来代替MySQL的函数,从而开启缓存。

 

2. EXPLAIN 你的 SELECT 查询

使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。

EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的……等等,等等。

挑一个你的SELECT语句(推荐挑选那个最复杂的,有多表联接的),把关键字EXPLAIN加到前面。你可以使用phpmyadmin来做这个事。然后,你会看到一张表格。下面的这个示例中,我们忘记加上了group_id索引,并且有表联接:

当我们为 group_id 字段加上索引后:

我们可以看到,前一个结果显示搜索了 7883 行,而后一个只是搜索了两个表的 9 和 16 行。查看rows列可以让我们找到潜在的性能问题。

3. 当只要一行数据时使用 LIMIT 1

当你查询表的有些时候,你已经知道结果只会有一条结果,但因为你可能需要去fetch游标,或是你也许会去检查返回的记录数。

在这种情况下,加上 LIMIT 1 可以增加性能。这样一样,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。

下面的示例,只是为了找一下是否有“中国”的用户,很明显,后面的会比前面的更有效率。(请注意,第一条中是Select *,第二条是Select 1)

1
2
3
4
5
6
7
8
9
10
11
// 没有效率的:
$r = mysql_query("SELECT * FROM user WHERE country = 'China'");
if (mysql_num_rows($r) > 0) {
    // ...
}
// 有效率的:
$r = mysql_query("SELECT 1 FROM user WHERE country = 'China' LIMIT 1");
if (mysql_num_rows($r) > 0) {
    // ...
}

4. 为搜索字段建索引

索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么,请为其建立索引吧。

从上图你可以看到那个搜索字串 “last_name LIKE ‘a%’”,一个是建了索引,一个是没有索引,性能差了4倍左右。

另外,你应该也需要知道什么样的搜索是不能使用正常的索引的。例如,当你需要在一篇大的文章中搜索一个词时,如: “WHERE post_content LIKE ‘%apple%’”,索引可能是没有意义的。你可能需要使用MySQL全文索引 或是自己做一个索引(比如说:搜索关键词或是Tag什么的)

5. 在Join表的时候使用相当类型的例,并将其索引

如果你的应用程序有很多 JOIN 查询,你应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动为你优化Join的SQL语句的机制。

而且,这些被用来Join的字段,应该是相同的类型的。例如:如果你要把 DECIMAL 字段和一个 INT 字段Join在一起,MySQL就无法使用它们的索引。对于那些STRING类型,还需要有相同的字符集才行。(两个表的字符集有可能不一样)

1
2
3
4
5
6
// 在state中查找company
$r = mysql_query("SELECT company_name FROM users
    LEFT JOIN companies ON (users.state = companies.state)
    WHERE users.id = $user_id");
// 两个 state 字段应该是被建过索引的,而且应该是相当的类型,相同的字符集。

6. 千万不要 ORDER BY RAND()

想打乱返回的数据行?随机挑一个数据?真不知道谁发明了这种用法,但很多新手很喜欢这样用。但你确不了解这样做有多么可怕的性能问题。

如果你真的想把返回的数据行打乱了,你有N种方法可以达到这个目的。这样使用只让你的数据库的性能呈指数级的下降。这里的问题是:MySQL会不得不去执行RAND()函数(很耗CPU时间),而且这是为了每一行记录去记行,然后再对其排序。就算是你用了Limit 1也无济于事(因为要排序)

下面的示例是随机挑一条记录

1
2
3
4
5
6
7
8
9
// 千万不要这样做:
$r = mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1");
// 这要会更好:
$r = mysql_query("SELECT count(*) FROM user");
$d = mysql_fetch_row($r);
$rand = mt_rand(0,$d[0] - 1);
$r = mysql_query("SELECT username FROM user LIMIT $rand, 1");

7. 避免 SELECT *

从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。

所以,你应该养成一个需要什么就取什么的好的习惯。

1
2
3
4
5
6
7
8
9
// 不推荐
$r = mysql_query("SELECT * FROM user WHERE user_id = 1");
$d = mysql_fetch_assoc($r);
echo "Welcome {$d['username']}";
// 推荐
$r = mysql_query("SELECT username FROM user WHERE user_id = 1");
$d = mysql_fetch_assoc($r);
echo "Welcome {$d['username']}";

8. 永远为每张表设置一个ID

我们应该为数据库里的每张表都设置一个ID做为其主键,而且最好的是一个INT型的(推荐使用UNSIGNED),并设置上自动增加的AUTO_INCREMENT标志。

就算是你 users 表有一个主键叫 “email”的字段,你也别让它成为主键。使用 VARCHAR 类型来当主键会使用得性能下降。另外,在你的程序中,你应该使用表的ID来构造你的数据结构。

而且,在MySQL数据引擎下,还有一些操作需要使用主键,在这些情况下,主键的性能和设置变得非常重要,比如,集群,分区……

在这里,只有一个情况是例外,那就是“关联表”的“外键”,也就是说,这个表的主键,通过若干个别的表的主键构成。我们把这个情况叫做“外键”。比如:有一个“学生表”有学生的ID,有一个“课程表”有课程ID,那么,“成绩表”就是“关联表”了,其关联了学生表和课程表,在成绩表中,学生ID和课程ID叫“外键”其共同组成主键。

9. 使用 ENUM 而不是 VARCHAR

ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。

如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。

MySQL也有一个“建议”(见第十条)告诉你怎么去重新组织你的表结构。当你有一个 VARCHAR 字段时,这个建议会告诉你把其改成 ENUM 类型。使用 PROCEDURE ANALYSE() 你可以得到相关的建议。

10. 从 PROCEDURE ANALYSE() 取得建议

PROCEDURE ANALYSE() 会让 MySQL 帮你去分析你的字段和其实际的数据,并会给你一些有用的建议。只有表中有实际的数据,这些建议才会变得有用,因为要做一些大的决定是需要有数据作为基础的。

例如,如果你创建了一个 INT 字段作为你的主键,然而并没有太多的数据,那么,PROCEDURE ANALYSE()会建议你把这个字段的类型改成 MEDIUMINT 。或是你使用了一个 VARCHAR 字段,因为数据不多,你可能会得到一个让你把它改成 ENUM 的建议。这些建议,都是可能因为数据不够多,所以决策做得就不够准。

在phpmyadmin里,你可以在查看表时,点击 “Propose table structure” 来查看这些建议

一定要注意,这些只是建议,只有当你的表里的数据越来越多时,这些建议才会变得准确。一定要记住,你才是最终做决定的人。

11. 尽可能的使用 NOT NULL

除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。这看起来好像有点争议,请往下看。

首先,问问你自己“Empty”和“NULL”有多大的区别(如果是INT,那就是0和NULL)?如果你觉得它们之间没有什么区别,那么你就不要使用NULL。(你知道吗?在 Oracle 里,NULL 和 Empty 的字符串是一样的!)

不要以为 NULL 不需要空间,其需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。

下面摘自MySQL自己的文档:

“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

12. Prepared Statements

Prepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。

Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击。当然,你也可以手动地检查你的这些变量,然而,手动的检查容易出问题,而且很经常会被程序员忘了。当我们使用一些framework或是ORM的时候,这样的问题会好一些。

在性能方面,当一个相同的查询被使用多次的时候,这会为你带来可观的性能优势。你可以给这些Prepared Statements定义一些参数,而MySQL只会解析一次。

虽然最新版本的MySQL在传输Prepared Statements是使用二进制形势,所以这会使得网络传输非常有效率。

当然,也有一些情况下,我们需要避免使用Prepared Statements,因为其不支持查询缓存。但据说版本5.1后支持了。

在PHP中要使用prepared statements,你可以查看其使用手册:mysqli 扩展 或是使用数据库抽象层,如: PDO.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 创建 prepared statement
if ($stmt = $mysqli->prepare("SELECT username FROM user WHERE state=?")) {
    // 绑定参数
    $stmt->bind_param("s", $state);
    // 执行
    $stmt->execute();
    // 绑定结果
    $stmt->bind_result($username);
    // 移动游标
    $stmt->fetch();
    printf("%s is from %s\n", $username, $state);
    $stmt->close();
}

13. 无缓冲的查询

正常的情况下,当你在当你在你的脚本中执行一个SQL语句的时候,你的程序会停在那里直到没这个SQL语句返回,然后你的程序再往下继续执行。你可以使用无缓冲查询来改变这个行为。

关于这个事情,在PHP的文档中有一个非常不错的说明: mysql_unbuffered_query() 函数:

“mysql_unbuffered_query() sends the SQL query query to MySQL without automatically fetching and buffering the result rows as mysql_query() does. This saves a considerable amount of memory with SQL queries that produce large result sets, and you can start working on the result set immediately after the first row has been retrieved as you don’t have to wait until the complete SQL query has been performed.”

上面那句话翻译过来是说,mysql_unbuffered_query() 发送一个SQL语句到MySQL而并不像mysql_query()一样去自动fethch和缓存结果。这会相当节约很多可观的内存,尤其是那些会产生大量结果的查询语句,并且,你不需要等到所有的结果都返回,只需要第一行数据返回的时候,你就可以开始马上开始工作于查询结果了。

然而,这会有一些限制。因为你要么把所有行都读走,或是你要在进行下一次的查询前调用mysql_free_result() 清除结果。而且, mysql_num_rows() 或 mysql_data_seek() 将无法使用。所以,是否使用无缓冲的查询你需要仔细考虑。

14. 把IP地址存成 UNSIGNED INT

很多程序员都会创建一个 VARCHAR(15) 字段来存放字符串形式的IP而不是整形的IP。如果你用整形来存放,只需要4个字节,并且你可以有定长的字段。而且,这会为你带来查询上的优势,尤其是当你需要使用这样的WHERE条件:IP between ip1 and ip2。

我们必需要使用UNSIGNED INT,因为 IP地址会使用整个32位的无符号整形。

而你的查询,你可以使用 INET_ATON() 来把一个字符串IP转成一个整形,并使用 INET_NTOA() 把一个整形转成一个字符串IP。在PHP中,也有这样的函数 ip2long() 和 long2ip()

1
$r = "UPDATE users SET ip = INET_ATON('{$_SERVER['REMOTE_ADDR']}') WHERE user_id = $user_id";

15. 固定长度的表会更快

如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理。

固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。

并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间。

使用“垂直分割”技术(见下一条),你可以分割你的表成为两个一个是定长的,一个则是不定长的。

16. 垂直分割

“垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。(以前,在银行做过项目,见过一张表有100多个字段,很恐怖)

示例一:在Users表中有一个字段是家庭地址,这个字段是可选字段,相比起,而且你在数据库操作的时候除了个人信息外,你并不需要经常读取或是改写这个字段。那么,为什么不把他放到另外一张表中呢? 这样会让你的表有更好的性能,大家想想是不是,大量的时候,我对于用户表来说,只有用户ID,用户名,口令,用户角色等会被经常使用。小一点的表总是会有好的性能。

示例二: 你有一个叫 “last_login” 的字段,它会在每次用户登录时被更新。但是,每次更新时会导致该表的查询缓存被清空。所以,你可以把这个字段放到另一个表中,这样就不会影响你对用户ID,用户名,用户角色的不停地读取了,因为查询缓存会帮你增加很多性能。

另外,你需要注意的是,这些被分出去的字段所形成的表,你不会经常性地去Join他们,不然的话,这样的性能会比不分割时还要差,而且,会是极数级的下降。

17. 拆分大的 DELETE 或 INSERT 语句

如果你需要在一个在线的网站上去执行一个大的 DELETE 或 INSERT 查询,你需要非常小心,要避免你的操作让你的整个网站停止相应。因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。

Apache 会有很多的子进程或线程。所以,其工作起来相当有效率,而我们的服务器也不希望有太多的子进程,线程和数据库链接,这是极大的占服务器资源的事情,尤其是内存。

如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让你泊WEB服务Crash,还可能会让你的整台服务器马上掛了。

所以,如果你有一个大的处理,你定你一定把其拆分,使用 LIMIT 条件是一个好的方法。下面是一个示例:

1
2
3
4
5
6
7
8
9
10
while (1) {
    //每次只做1000条
    mysql_query("DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000");
    if (mysql_affected_rows() == 0) {
        // 没得可删了,退出!
        break;
    }
    // 每次都要休息一会儿
    usleep(50000);
}

18. 越小的列会越快

对于大多数的数据库引擎来说,硬盘操作可能是最重大的瓶颈。所以,把你的数据变得紧凑会对这种情况非常有帮助,因为这减少了对硬盘的访问。

参看 MySQL 的文档 Storage Requirements 查看所有的数据类型。

如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。

当然,你也需要留够足够的扩展空间,不然,你日后来干这个事,你会死的很难看,参看Slashdot的例子(2009年11月06日),一个简单的ALTER TABLE语句花了3个多小时,因为里面有一千六百万条数据。

19. 选择正确的存储引擎

在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。酷壳以前文章《MySQL: InnoDB 还是 MyISAM?》讨论和这个事情。

MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。

InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。

下面是MySQL的手册

20. 使用一个对象关系映射器(Object Relational Mapper)

使用 ORM (Object Relational Mapper),你能够获得可靠的性能增涨。一个ORM可以做的所有事情,也能被手动的编写出来。但是,这需要一个高级专家。

ORM 的最重要的是“Lazy Loading”,也就是说,只有在需要的去取值的时候才会去真正的去做。但你也需要小心这种机制的副作用,因为这很有可能会因为要去创建很多很多小的查询反而会降低性能。

ORM 还可以把你的SQL语句打包成一个事务,这会比单独执行他们快得多得多。

目前,个人最喜欢的PHP的ORM是:Doctrine

21. 小心“永久链接”

“永久链接”的目的是用来减少重新创建MySQL链接的次数。当一个链接被创建了,它会永远处在连接的状态,就算是数据库操作已经结束了。而且,自从我们的Apache开始重用它的子进程后——也就是说,下一次的HTTP请求会重用Apache的子进程,并重用相同的 MySQL 链接。

在理论上来说,这听起来非常的不错。但是从个人经验(也是大多数人的)上来说,这个功能制造出来的麻烦事更多。因为,你只有有限的链接数,内存问题,文件句柄数,等等。

而且,Apache 运行在极端并行的环境中,会创建很多很多的了进程。这就是为什么这种“永久链接”的机制工作地不好的原因。在你决定要使用“永久链接”之前,你需要好好地考虑一下你的整个系统的架构。

文章:来源

(全文完)

Servername与Serveralias是什么意思 | 有什么区别

可以先看我搜到的一篇文章《Apache中的ServerName和ServerAlias》

在Apache中添加虚拟主机(Virtualhost)记录时:

<VirtualHost *:80>
ServerAdmin admin@localhost
DocumentRoot “e:/www/team”
ServerName team.renrenstudy.com
#ServerAlias company.renrenstudy.com
ErrorLog “logs/vhosts/team_error.log”
CustomLog “logs/vhosts/team_access.log” common
</VirtualHost>

ServerName即是要添加的域名,在本例中也就是team.renrenstudy.com,如果别人访问这个域名,那么将被Apache自动解析到e:/www/team这个目录下,也就是本例中的DocumentRoot所指定的目录。

这时,我想让别人访问company.renrenstudy.com也能解析到这个目录,那么就用到ServerAlias了。Alias的中文意思就是别名,这里就相当于给team.renrenstudy.com起了个别名叫company.renrenstudy.com。

大家也可以查看我的另一个篇文章,介绍了如何在Apache服务器中配置虚拟主机,《Apache中配置虚拟主机 | How to config vitualhost in apache》

大家如果还有疑问,请在下方评论中给出,我会及时回答。

Apache中配置虚拟主机 | How to config virtualhost in apache

虚拟主机技术的产生,使得一台服务器可以在外部看做多台独立服务器,极大地降低了大家建立网站的成本。在这里,我们介绍一下如何在Apache中虚拟主机的配置方法。

首先看一下下面这篇文章,里面还包含了IIS中虚拟主机的配置方法。

虚拟主机是指在一台服务器里运行几个网站、提供WEB、FTP、Mail等服务。本文主要介绍WEB服务的虚拟主机设置。

虚拟主机有两种实现方法:基于IP的方法和基于主机名的方法。

基于IP的方法:

首先,在服务器里绑定多个IP,然后配置WEB服务器,把多个网站绑定在不同的IP上。访问不同的IP,就看到不同的网站。

基于主机名的方法:

首先,设置多个域名的A记录,使它们解析到同一个IP地址上,即同一个服务器上。然后,在服务器上配置WEB服务端,添加多个网站,为每个网站设定一个主机名。因为HTTP协议访问请求里包含有主机名信息,当WEB服务器收到访问请求时,就可以根据不同的主机名来访问不同的网站。

基本IP的方法在局域网中比较常用,基于主机名的方法在Internet中比较常用。下面以两个最常用的WEB服务器IIS和Apache为例,介绍基于主机名的虚拟主机的设置方法。

设置虚拟主机的主要步骤:

1、在动态域名客户端软件里添加多个域名。这一步的目的,是让这些域名都解析到同一个服务器上。(注:公网客户端和内网专业版TrueHost客户端可添加多个域名,内网标准版不支持多域名)。

2、在用户机器的WEB服务器(IIS、Apache等)上添加域名配置虚拟主机。

IIS虚拟主机设置

1、打开“控制面板”->“管理工具”->“Internet服务管理器”->“默认web站点”。

2、在“默认web站点”上按鼠标右键,选择“新建”->“站点”。按“下一步”。

3、输入站点说明,如“站点1”。按“下一步”。

4、在“站点的主机头”上输入域名,如“abc.dns0755.net”。按“下一步”。

5、在路径里指定站点的根目录路径。按“下一步”。

6、在权限里选择适当的权限。按“下一步”,即可完成。

如果配置的是顶级域名的虚拟主机,例如在上面第4步主机头里输入“xkzzz.com”,而同时又希望用户使用“www.xkzzz.com”也能访问。设置步骤如下:

1、在“Internet服务管理器”的“站点1”上按鼠标右键,选择“属性”。

2、在IP地址右边点击“高级”。

3、点击“添加”,输入端口号(一般用80),再输入主机头名“www.xkzzz.com”。

如果有多个站点要添加,请重复执行上面的步骤。

Apache虚拟主机设置

1、打开Apache配置文件“httpd.conf”,查找“#NameVirtualHost *”,把这行前面的“#”去掉。

2、在“NameVirtualHost *”这行下面,增加虚拟主机站点。示例如下:

<VirtualHost *>

ServerAdmin webmaster@comexe.cn

DocumentRoot /export/home/dns0755

ServerName dns0755.net

ServerAlias *.dns0755.net

ErrorLog “| /usr/local/sbin/rotatelogs /var/log/http/dns0755-err.log 604800”

CustomLog “| /usr/local/sbin/rotatelogs /var/log/http/dns0755.log 604800” combined

</VirtualHost>

说明:

ServerAdmin webmaster@comexe.cn

站点管理员Email地址

DocumentRoot /home/dns0755

站点根目录

ServerName dns0755.net

站点主机名

ServerAlias *.dns0755.net

站点别名,“*”表示任意字符

ErrorLog “| /usr/local/sbin/rotatelogs /var/log/http/dns0755-err.log 604800”

错误日志控制

CustomLog “| /usr/local/sbin/rotatelogs /var/log/http/dns0755.log 604800” combined

访问日志

/usr/local/sbin/rotatelogs是日志管理程序

/var/log/http/dns0755.log是日志文件名

604800的单位是秒,这种写法表示每隔7天产生一个日志文件

如果有多个站点要添加,请重复执行第2步操作。

大家如果还有不明白,或者不确定的地方,可以参看下面我总结的几个步骤

1、在httpd.conf文件中找到这样一行:#Include conf/extra/httpd-vhosts.conf

如果有,就把前面的#去掉。如果没有这行,没关系,直接在httpd.conf文件末尾加上这行即可(需要把前面的#去掉)。

2、找到Apache目录下的conf/extra/httpd-vhosts.conf文件,用记事本打开。

3、httpd-vhosts.conf里面应该是有内容的。我们就是要在这里配置虚拟主机信息的。

4、给大家一个例子大家就能看懂了:

NameVirtualHost *:80

<VirtualHost *:80>
ServerAdmin admin@localhost
DocumentRoot “e:/www/team”
ServerName team.renrenstudy.com
#ServerAlias team1.renrenstudy.com
ErrorLog “logs/vhosts/team_error.log”
CustomLog “logs/vhosts/team_access.log” common
</VirtualHost>

5、解释一下上面的例子

最重要的两行就是

DocumentRoot “e:/www/team”
ServerName team.renrenstudy.com

这里DocumentRoot指定了要添加虚拟主机的网站根目录,ServerName就是该虚拟主机的域名。

论坛迁移后Discuz的UCenter出错无法访问

论坛迁移后,大家都知道修改论坛根目录下config文件夹中的两个文件,将新新服务器的数据库等信息修改过来。

但往往修改这两个文件后,论坛仍然无法正常访问,或者UCenter访问出错,这是怎么回事呢?

其实,迁移服务器后,还有一个配置文件需要修改,即\uc_server\data\config.inc.php,将里面的数据库等配置信息也更改后,应该就解决问题了。