Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18673141
  • 博文数量: 7460
  • 博客积分: 10434
  • 博客等级: 上将
  • 技术积分: 78178
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-02 22:54
文章分类

全部博文(7460)

文章存档

2011年(1)

2009年(669)

2008年(6790)

分类:

2008-03-20 09:53:58

存取 MySQL

透过网页存取数据库内容的程序,多半要遵循以下几个步骤来进行:

建立数据库联机
选定欲存取的数据库
执行查询动作
取出查询结果
中断数据库联机
以下将针对这几个步骤一一加以说明。


建立数据库联机

我们将存取数据库的过程,想象成一艘货轮要进港载货。首先,港务局(MySQL)会对我们进行身分验证,以确定是否为货物的拥有者。在通过身分验证之后,我们将会得到一张「识别证」。

一般而言,港务局会开放 3306 号港口(port)供我们上下货物,因此我们不必多费唇舌,可以直接驶入其中;否则,我们还要将货轮驶向特定的港口停放。

    $link = mysql_connect(HOSTNAME, USERNAME, PASSWORD);
    $link = mysql_connect(HOSTNAME:PORT, USERNAME, PASSWORD);

上面这行叙述在对 MySQL 表明存取者的身分。其中的 HOSTNAME 是「主机名称」,若 Web server 与 MySQL 同在一部机器上的话,可以写成「localhost」,否则请写数据库主机的名称或 IP。USERNAME 与 PASSWORD 所指的就是要存取 MySQL 的账号密码了。

一般的情况下,MySQL 会透过 3306 port 运作。若系统使用这项默认值的话,我们可以不用再加指定;否则请额外加入 PORT 参数来说明,如:「localhost:9000」。

透过 mysql_connect( ) 的运作,MySQL 可以确认数据存取者的身分。成功的话,将回传一个「link identifier」;否则传回 FALSE。


选定欲存取的数据库

取得通行许可之后,接着进入货物区。这里可能会有许多间货品仓库(数据库),我们还要向管理员出示「识别证」,并从中挑选一间仓库。

    mysql_select_db(DBNAME);
    mysql_select_db(DBNAME, Identifier);

上面的 DBNAME 指的是「数据库名称」,当面对单一数据库时,Identifier 可以省略不写。

由于存取每个数据库都需要一个个别的 link identifier,所以若我们想同时存取两个数据库时,必须建立两个 link identifier ,并在 mysql_select_db( ) 里指明哪一个 link identifier 将对应到哪一个数据库。


执行查询动作

此时,无论是要将货物搬上船,或是将船上的货品存放到仓库中,请将工作清单(QueryString)拿出来,然后就可以开工了。

    $result = mysql_query(QueryString);
    $result = mysql_query(QueryString, Identifier);
    $result = mysql_db_query(DBNAME, QueryString, Identifier);

QueryString 即我们对数据库的查询动作,它可能是一段数据查询的叙述,也可能是新增、修改或删除等异动数据的要求。当 $result 为 FALSE 时,表示这个存取动作是失败的;否则,它将会是一个编号(ID)。在「取出查询结果」的步骤,我们得靠它来识别这次的查询结果。

在使用 mysql_query( ) 时,Identifier 是可以省略不写的。若我们不加以指定的话,系统会自动选用最近一次被使用的 link identifier。

如果我们先前「选定欲存取的数据库」这个步骤略过的话,现在可以改用 mysql_db_query( ) 来进行资料查询的动作。也就是说,mysql_db_query( ) 的功能等同于 mysql_select_db( ) 加上 mysql_query( )。


取出查询结果

取得货物以后,拆开来看吧!里头分装成一箱一箱的,我们可以算算有多少箱,也可以再把箱子拆开,取出里面的货品来。

在上个步骤中,若我们执行的是查询动作的话,MySQL 会将结果包装成一个 result set,并传回它的编号(ID),接下来要读取数据时,都少不了它。

    $number_of_rows = mysql_num_rows($result);

藉由 mysql_num_rows( ) 函数,我们可以得知这个 result set 里头有多少个数据列(row)。

最后,再透过循环的运作,将 result set 里的每个资料列一一读出来。由于每个数据列可能含有多个字段,所以 $data 将会是一个数组;要一一显示个别字段内容的话,我们可以用 $data[0]、$data[1]、$data[2]、...... 的方式。

    for ( $i=0; $i<$number_of_rows; $i++ ) {
        $data = mysql_fetch_row($result);
        echo $data[0];
        ......
    }

要不然,使用以下这种方式也行:将各个字段的值存入相对应的变量中。

    for ( $i=0; $i<$number_of_rows; $i++ ) {
        list($value1, $value2, $value3, ......) = mysql_fetch_row($result);
        echo $value1;
        ......
    }


中断数据库联机

任务达成,向港务局 say good bye 吧!

    mysql_close(Identifier);

mysql_close( ) 可以用来关闭一个由 mysql_connect( ) 所建立的数据库连结,但是这个动作不是必要的。因为当一支程序执行结束之后,数据库连结会被自动中断。



经验谈

在建立数据库联机时,除了上述的 mysql_connect( ) 以外,您也可以使用 mysql_pconnect( ) 来建立一个持续性的联机(persistent connection)。

用 mysql_connect( ) 建立的联机,用完即丢,干净利落。不过,因为在建立数据库联机时,需要耗费一些时间与系统资源;若使用「持续联机」的话,同一部 web server 再向 MySQL server 请求联机时,可以直接使用先前用完闲置的联机,而不必重建。所以使用 mysql_pconnect( ) 来建立联机,可以节省时间,同时也能降低服务器的负担。

两者相较之下,mysql_pconnect( ) 显然好得多,以后我们都使用它就好了。一般而言,这样的说法是对的,坊间的相关书籍几乎都支持这个论点;但我觉得它不完全正确,也就是说:在某些场合,mysql_pconnect( ) 是不适用的。


--------------------------------------------------------------------------------

状况一:

使用 1 部 web server 与 1 部 MySQL server(两者可能同在一部主机上),而 web server 固定只对 MySQL server 上的某一个数据库进行存取动作。

因为每次存取数据库时,都是由 web 那边使用同一账号对 MySQL 上的同一数据库作业,若我们将 MySQL 与 web server 的「同时联机数」都调整为 200,就好像 MySQL 这边一直有 200 位「服务生」,随时等着接待来自 web 的 200 位「顾客」似的。而且「顾客」离开之后,「服务生」也不下场休息,时时都站在门口等着接待下一个「顾客」。

在这种情况下,您只要注意将 MySQL 的「同时联机数」调得比 web server 的高或相等,就会发现使用 mysql_pconnect( ) 是个不错的选择。


--------------------------------------------------------------------------------

状况二:

使用 1 部 web server 与 1 部 MySQL server(两者可能同在一部主机上),而 web server 会对 MySQL server 上的两个数据库进行存取动作。

从 web server 那边提出数据存取需求时,有时是针对第 1 个数据库(DB1),有时则是针对第 2 个数据库(DB2)。若我们也将 MySQL 与 web server 的「同时联机数」都调整为 200,这样一来,就好像 MySQL 这边有 200 位「服务生」,但同时经营两个「吧台」(DB1 与 DB2),而「顾客」可能多达 200 位。

一开始,DB1 这个「吧台」比较热门,MySQL 派了 150 位「服务生」上场接待;同样地,当「顾客」离开之后,这 150 位「服务生」仍守着 DB1 而不下场休息。后来,DB2 那边也热闹起来了,「顾客」越来越多,MySQL 得加派「服务生」上场,有几个能派?答案是 50 个!

为什么「服务生」的人力调配会捉襟见肘?那是因为 web 那边使用了 mysql_pconnect( ) 来建立联机。「服务生」一开始被指定到哪个「吧台」工作,就会持续在那边停留,绝不「转台」。


--------------------------------------------------------------------------------

请注意,当使用持续性的联机时,每个已建立的联机只为来自同一部 web server、使用同一组账号,且存取同一数据库的使用者服务。

如此一来,假设每部 web server 的「同时联机数」都是 200,而且同时使用 2 部 web server 会怎么样呢?从 web1 来了 50 个「顾客」,先是到 DB1 走一趟,接着再到 DB2 晃一圈,这样需要多少「服务生」接待他们?100 个(web1->DB1: 50 web1->DB2: 50)!又从 web2 来了 50 个「顾客」,也做了同样的动作(web2->DB1: 50 web2->DB2: 50)。在此之后,还有「服务生」是闲着的吗?后续若从 web1 或 web2 同时涌入多于 50 位「顾客」时,谁来应付他们?

倘若您使用的是像 Apache 这类的 multi-process web server(一个 parent process 协调一组 children processes 运作),某个 children process 建立的「持续联机」,是不能分享给其它 children process 来使用的(「服务生」只对先前接待过的「顾客」服务)。在这样的情况下,将会使得 MySQL 上闲置的 process 越积越多(很多「服务生」站在门口等着「老顾客」上门,而不理会「新顾客」)。

mysql_pconnect( ) 一定是最佳选择吗?我想未必尽然。


--------------------------------------------------------------------------------

说明:

「同时联机数」是有上限的,当所有联机都被占用时,后续的联机要求就会被拒绝。「同时联机数」能调整到多高,这与服务器本身的效能是息息相关的,因为调得愈高,所消耗的系统资源也就愈多。
阅读(615) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~