找回密码
 注册

QQ登录

只需一步,快速开始

查看: 876|回复: 6

Developing MySQL Database Applications With PHP Part 4

[复制链接]
发表于 2011-8-4 15:17:03 | 显示全部楼层 |阅读模式
Using the MySQL Native Driver for PHP, mysqlnd
This series of tutorials shows the essential steps involved in installing PHP with MySQL extensions mysql, mysqli, and pdo_mysql, and with support for the MySQL native driver for PHP, mysqlnd. The tutorials also provide simple examples to connect, insert, and retrieve data from a MySQL database. Because the focus is on database connectivity from a PHP script, these tutorials assume that some kind of MySQL database is already up and accessible from the client machine.

For general information about accessing MySQL with PHP database extensions, a list of the major PHP API offerings, and instructions on setting up the test database used in these tutorials, see the first sections of the first tutorial in this series, Developing MySQL Database Applications With PHP Part 1: Using the MySQL Improved Extension, mysqli.

Application developers who are new to the development of MySQL database applications with PHP are the target audience of this article.

Contents


Use the MySQL Native Driver for PHP, mysqlnd



To communicate with the MySQL database server, the extensions mysql and mysqli and the pdo_mysql driver rely on the MySQL client library, libmysql. The MySQL native driver for PHP (referred to as mysqlnd from this point) is an additional, alternative way to connect from PHP 5 and PHP 6 to the MySQL Server 4.1 or later versions. The mysqlnd driver is a replacement for the MySQL client library, libmysql, and it is tightly integrated into PHP starting with the release of PHP 5.3. That is, from PHP 5.3 onwards the developer can choose between libmysql and mysqlnd when using ext/mysql, ext/mysqli, or PDO extensions to connect to the MySQL server 4.1 or newer. Due to the tight integration into PHP 5.3 (and later), mysqlnd eliminates the dependency on the MySQL client programming support when the database extensions and the database driver are built with the support for mysqlnd.

The mysqlnd driver is not another PHP extension like mysqli, and it does not have an API that is exposed to the user. It is a library that provides similar functionality to that of the MySQL client library, libmysql. The mysqlnd and libmysql libraries implement the MySQL communication protocol, hence both of those libraries can be used to connect to the MySQL Server.
Because mysqlnd is neither a new extension nor a programming API, but just an alternative to libmysql to connect from PHP to the MySQL Server, there is no need to make changes to the existing PHP scripts. Existing scripts that are running properly with ext/mysql, ext/mysqli, and PDO extensions built with libmysql support continue to run with the exact same behavior even when the ext/mysql, ext/mysqli, and PDO extensions are built with mysqlnd support.

From the performance perspective, mysqlnd might be as fast as libmysql and might even outperform libmysql in some cases. The generic recommendation is to try mysqlnd with your PHP application and then decide based on the performance results.

Some of the advantages of using mysqlnd are listed below:

  • Easy to compile: No linking against libmysql, and no dependency on the MySQL client programming support
  • Might outperform libmysql in certain cases
  • Persistent connections for ext/mysqli
  • Uses PHP memory management, and supports PHP memory limit
  • Keeps every row only once in memory, whereas with libmysql you have every row twice in memory
  • Keeps a long list of performance-related statistics for bottleneck analysis

Install PHP With the MySQL Native Driver, mysqlnd



Because most of the prepackaged PHP binary installations might not have the support for mysqlnd enabled by default, it is recommended to build PHP and the required database extensions with mysqlnd from the source code. The rest of this section focuses on the installation of PHP 5.3 from the source code.

  • Get the source code for PHP 5.3 or later versions from the PHP.net site or from the PHP Snapshot build site.
  • Make sure that Autoconf 2.13 or later and GNU M4 1.4.7 or later are installed on the build machine. Adjust the PATH environment variable to include the path to the autoconf and m4 tools.

    For example:
    1. bash# ls /usr/local/bin/autoconf /usr/local/bin/m4
    2. /usr/local/bin/autoconf  /usr/local/bin/m4

    3. bash# export PATH=.:/usr/local/bin:$PATH
    复制代码

  • On the Sun Solaris OS, create a soft link to gmake in the source directory.

    bash# ln -s /usr/bin/gmake make

  • Navigate to the source directory and run buildconf.

    For example:
    1. bash# cd php5.3-200811132130
    2. bash# ./buildconf --force
    复制代码

  • For building PHP 5.3 or later with mysqlnd support on Unix or Linux systems, you can decide for all three MySQL extensions (ext/mysql, ext/mysqli, and PDO_mysql) whether they should be built using mysqlnd or libmysql. When choosing mysqlnd, use the string mysqlnd as the path to the mysql client library. If you don't specify the string mysqlnd as the library location, by default, PHP tries to use libmysql. It is possible to build one extension with one library and another extension with another library. For example, you can build the mysqli extension with mysqlnd support, and PDO_MYSQL with libmysql.

    The configure option shown below builds all the three extensions with mysqlnd support.

    For example:

            bash# ./configure --prefix=/export/home/php53 --enable-mysqlnd --with-mysqli=shared,mysqlnd --with-mysql=shared,mysqlnd \        --with-pdo-mysql=shared,mysqlnd --with-zlib=shared [other options]


    The configure script in PHP 6.0 and some builds of PHP 5.3 might not recognize the --enable-mysqlnd option, so check the configure options by running ./configure --help before specifying --enable-mysqlnd in the list of configure options to build PHP.

    On the Windows platform, ext/mysqli uses the MySQL native driver by default in PHP versions 5.3 and newer. Hence you don't need to configure libmysql.dll.
  • On the Sun Solaris OS, pass the -z muldefs option to the linker to proactively defend against linker errors like ld: fatal: symbol `<symbol>' is multiply-defined.

    bash# export LDFLAGS="-z muldefs"

  • Build PHP.

    bash# make

  • Install PHP in the destination location.

    bash# make install

  • Enable the required database extensions in php.ini.

    For example:
    1. bash# grep extension php.ini | grep -v \;

    2. extension_dir=/export/home/php53/lib/php/extensions/no-debug-non-zts-20071006
    3. extension="mysql.so"
    4. extension="mysqli.so"
    5. extension="pdo_mysql.so"
    复制代码


  • Finally, verify the new PHP installation by checking the list of PHP modules.

    For example:
    1. bash# cd /export/home/php53/bin

    2. bash# ./php -m | grep mysql
    3. mysql
    4. mysqli
    5. mysqlnd
    6. pdo_mysql

    7. bash# ./php -i | grep -i mysql
    8. ..
    9. mysql
    10. MySQL Support => enabled
    11. Client API version => mysqlnd 5.0.5-dev - 081106 - $Revision: 1.3.2.18 $
    12. ..
    13. mysqli
    14. MysqlI Support => enabled
    15. Client API library version => mysqlnd 5.0.1-beta - 070402 - $Revision: 321 $
    16. ..
    17. mysqlnd
    18. mysqlnd => enabled
    19. Version => mysqlnd 5.0.5-dev - 081106 - $Revision: 1.3.2.18 $
    20. ..
    21. pdo_mysql
    22. PDO Driver for MySQL => enabled
    23. Client API version => mysqlnd 5.0.5-dev - 081106 - $Revision: 1.3.2.18 $
    24. ..

    复制代码



 楼主| 发表于 2011-8-4 15:21:45 | 显示全部楼层
Test the MySQL Database Connectivity


As mentioned earlier, merely replacing libmysql with mysqlnd does not force PHP developers to rewrite their applications. Hence we can use any of the existing code samples in this tutorial series to demonstrate successful database connectivity with mysqlnd under the hood. The following example displays the output from a PHP interpreter that is built with mysqlnd support. The ext/mysqli extension is also built with mysqlnd support. The PHP script used in the following example was originally shown in Developing MySQL Database Applications With PHP Part 1: Using the MySQL Improved Extension, mysqli.

For example:
  1. bash# export LD_DEBUG=symbols,libs

  2. bash# export LD_DEBUG_OUTPUT=lddebug.log

  3. bash# /export/home/php53/bin/php PHPmysqliClient.php

  4. Retrieved 3 row(s).

  5. CityName
  6. --------
  7. Hyderabad, India
  8. San Francisco, USA
  9. Sydney, Australia

  10. bash# unset LD_DEBUG LD_DEBUG_OUTPUT
  11. bash# grep libmysql lddebug.log*
  12. bash#
复制代码

Notice zero references to the libmysql library in the runtime linker's diagnostic debugging information.

Support for Persistent Connections


The extensions ext/mysql and ext/mysqli and the driver PDO_MySQL support persistent connections when built with mysqlnd. For more information about persistent connections, see the section "Persistent Database Connections" in the tutorial Developing MySQL Database Applications With PHP Part 2: Using the MySQL Extension, mysql. Note that ext/mysqli does not support persistent connections when built with libmysql. However ext/mysqli does support persistent connections when built with mysqlnd. For example, to establish a persistent connection with the MySQL Server using ext/mysqli and mysqlnd, prefix the database host with the string "p:" (p stands for persistent) as shown below.
  1. $host="p:localhost";
  2. $port=3306;
  3. $socket="/tmp/mysql.sock";
  4. $user="root";
  5. $password="admin";
  6. $dbname="test";

  7. $cxn = new mysqli($host, $user, $password, $dbname, $port, $socket)
  8.         or die ('Could not connect to the database server' . mysqli_connect_error());
复制代码

While the persistent connections might improve the performance for some applications, especially running over slow network links, they can lead to trouble if not used properly. For example, if you lock a table and close the database connection before unlocking it, normally it is unlocked when the connection is terminated. However because persistent connections do not close, any tables you accidentally leave locked remain locked, and the only way to unlock them is probably to wait for the connection to time out or kill the process. Also due to the persistent nature of the connections, the process can consume more resources.
Calling mysqli::change_user() can alleviate the issue to some extent. Using this method always causes the current database connection to behave as if it is a completely new database connection regardless of whether the operation is completed successfully. mysqli::change_user() rolls back any active transactions, closes all temporary tables, and unlocks all the locked tables.

Alternatively, you can register a function that does an explicit rollback of non-committed transactions on script shutdown, with register_shutdown_function(). Do your due diligence in finding the right function that fits your needs in terms of the performance and the functionality.



 楼主| 发表于 2011-8-4 15:22:33 | 显示全部楼层
mysqlnd's Memory Savings


The mysqlnd driver can save memory. In the best cases, it consumes only 50% as much memory as that of libmysql, especially when the client application does not modify the data in the result set after executing a query. Keep in mind that the client must use ext/mysqli and treat the data returned by the query as read-only to fully realize mysqlnd's memory gains. If the client application modifies any of the data, mysqlnd behaves just like libmysql.

Let's have a quick look at the memory consumption in both the cases (mysqlnd and libmysql) with an example before delving into the internals. For easy comparison, the sample PHP script does not modify any of the arrays returned from the fetch method. The following example uses DTrace on the Sun Solaris OS to monitor the calls to malloc() and prints the requested bytes of memory on the standard output.
  1. bash# cat monitormalloc.d

  2. #!/usr/sbin/dtrace -s

  3. pid$1:libc:malloc:entry
  4. {
  5.         printf("\t\tSize : %d Bytes", arg0);
  6.         ustack();
  7.         @malloc[probefunc] = quantize(arg0);
  8. }

  9. CASE 1: ext/mysqli with libmysql

  10. In one terminal window:

  11. bash# /opt/coolstack/php5/bin/php PHPmysqliClient.php

  12. In another terminal window, run monitormalloc.d `pgrep php` and press any key to continue ..

  13. Retrieved 3 row(s).

  14. CityName
  15. --------
  16. Hyderabad, India
  17. San Francisco, USA
  18. Sydney, Australia

  19. In another terminal window:

  20. bash# ./monitormalloc.d `pgrep php`
  21. dtrace: script './monitormalloc.d' matched 1 probe
  22. CPU     ID                    FUNCTION:NAME
  23.   0  80920                     malloc:entry                 Size : 964 Bytes
  24.               libc.so.1`malloc
  25.               libmysqlclient.so.16.0.0`0xce2173c1
  26.               libmysqlclient.so.16.0.0`0xce23bb47
  27.               mysqli.so`0xce11d292

  28.   0  80920                     malloc:entry                 Size : 20 Bytes
  29.               libc.so.1`malloc
  30.               libmysqlclient.so.16.0.0`0xce2173c1
  31.               libmysqlclient.so.16.0.0`0xce23da60
  32.               mysqli.so`0xce11dc72

  33.   0  80920                     malloc:entry                 Size : 20 Bytes
  34.               libc.so.1`malloc
  35.               libmysqlclient.so.16.0.0`0xce2173c1
  36.               libmysqlclient.so.16.0.0`0xce21d991
  37.               libmysqlclient.so.16.0.0`0xce21d9ce
  38.               libmysqlclient.so.16.0.0`0xce23da72
  39.               mysqli.so`0xce11dc72

  40.   0  80920                     malloc:entry                 Size : 17 Bytes
  41.                 ... elided stack traces for brevity ...
  42.   0  80920                     malloc:entry                 Size : 152 Bytes
  43.   0  80920                     malloc:entry                 Size : 16384 Bytes
  44.   0  80920                     malloc:entry                 Size : 8199 Bytes
  45.   0  80920                     malloc:entry                 Size : 7 Bytes
  46.   0  80920                     malloc:entry                 Size : 4088 Bytes
  47.   0  80920                     malloc:entry                 Size : 4088 Bytes
  48.   0  80920                     malloc:entry                 Size : 4088 Bytes
  49.   0  80920                     malloc:entry                 Size : 4088 Bytes
  50.   0  80920                     malloc:entry                 Size : 4088 Bytes
  51.   0  80920                     malloc:entry                 Size : 4088 Bytes
  52.   0  80920                     malloc:entry                 Size : 4088 Bytes
  53.   0  80920                     malloc:entry                 Size : 4088 Bytes
  54.   0  80920                     malloc:entry                 Size : 4088 Bytes
  55.   0  80920                     malloc:entry                 Size : 18261 Bytes
  56.   0  80920                     malloc:entry                 Size : 58 Bytes
  57.   0  80920                     malloc:entry                 Size : 4088 Bytes
  58.   0  80920                     malloc:entry                 Size : 4088 Bytes
  59.   0  80920                     malloc:entry                 Size : 120 Bytes
  60.   0  80920                     malloc:entry                 Size : 5 Bytes
  61.   0  80920                     malloc:entry                 Size : 6 Bytes
  62.   0  80920                     malloc:entry                 Size : 5 Bytes
  63.   0  80920                     malloc:entry                 Size : 56 Bytes
  64.   0  80920                     malloc:entry                 Size : 8164 Bytes
  65.   0  80920                     malloc:entry                 Size : 8164 Bytes
  66.   0  80920                     malloc:entry                 Size : 92 Bytes
  67.   0  80920                     malloc:entry                 Size : 56 Bytes
  68.   0  80920                     malloc:entry                 Size : 8164 Bytes
  69.               libc.so.1`malloc
  70.               libmysqlclient.so.16.0.0`0xce2173c1
  71.               libmysqlclient.so.16.0.0`0xce21a27b
  72.               libmysqlclient.so.16.0.0`0xce23b8a4
  73.               libmysqlclient.so.16.0.0`0xce23d4fa
  74.               mysqli.so`0xce11fe56

  75.   0  80920                     malloc:entry                 Size : 262144 Bytes
  76.               libc.so.1`malloc
  77.               php`0x856fb98

  78. ^C

  79.   malloc                                            
  80.            value  ------------- Distribution ------------- count   
  81.                2 |                                         0        
  82.                4 |@@@@@                                    4        
  83.                8 |                                         0        
  84.               16 |@@@@                                     3        
  85.               32 |@@@@                                     3        
  86.               64 |@@@                                      2        
  87.              128 |@                                        1        
  88.              256 |                                         0        
  89.              512 |@                                        1        
  90.             1024 |                                         0        
  91.             2048 |@@@@@@@@@@@@@@                           11      
  92.             4096 |@@@@                                     3        
  93.             8192 |@                                        1        
  94.            16384 |@@@                                      2        
  95.            32768 |                                         0        
  96.            65536 |                                         0        
  97.           131072 |                                         0        
  98.           262144 |@                                        1        
  99.           524288 |                                         0        

  100. CASE 2: ext/mysqli with mysqlnd

  101. In one terminal window:

  102. bash# /export/home/php53/bin/php PHPmysqliClient.php
  103. In another terminal window, run monitormalloc.d `pgrep php` and press any key to continue ..

  104. Retrieved 3 row(s).

  105. CityName
  106. --------
  107. Hyderabad, India
  108. San Francisco, USA
  109. Sydney, Australia

  110. In another terminal window:

  111. bash# ./monitormalloc.d `pgrep php`
  112. dtrace: script './monitormalloc.d' matched 1 probe
  113. CPU     ID                    FUNCTION:NAME
  114.   0  80920                     malloc:entry                 Size : 262144 Bytes
  115.               libc.so.1`malloc
  116.               php`0x82f702b
  117.               php`0x82f80ab
  118.               php`0x82f841f
  119.               php`0x82f98c4
  120.               php`0x82c7668
  121.               php`0x83c30ae
  122.               php`0x80c059c

  123. ^C

  124.   malloc                                            
  125.            value  ------------- Distribution ------------- count   
  126.           131072 |                                         0        
  127.           262144 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1        
  128.           524288 |                                         0        
复制代码

In the case of ext/mysqli with libmysql, there are more than 25 calls to malloc() accounting for a total size around 367 KB, whereas in the case of ext/mysqli with mysqlnd, there is only one call to malloc() with a size of 256 KB. In other words, mysqlnd is consuming 30% less memory relative to libmysql to do similar database operations. (In reality, it is incorrect to treat every byte allocated as the memory consumed unless there exists a corresponding memory mapping -- however for the sake of simplicity, let's assume that all the allocated bytes are eventually consumed.)

The memory savings in the above example are the result of mysqlnd's ability to hold the results only once in the memory. On the other hand, because libmysql is not a part of PHP, some of the results fetched by libmysql are copied into memory twice. When libmysql fetches the data from the MySQL Server, it puts the data into its own buffers. Then the data gets copied from the libmysql buffers into respective ext/mysqli data structures (often referred as zvals) before it is made available to the PHP clients to consume. So with ext/mysqli and libmysql, there might be two copies of the data in the main memory: one copy inside the libmysql buffers and the other inside zvals. With mysqlnd, there might be only one copy of the data in the memory. The mysqlnd driver also uses buffers but links the zval structures directly to the read buffers, wherever possible. Therefore in a majority of instances, mysqlnd consumes less memory relative to libmysql. In the worst case, it can consume as much memory as that of libmysql. The total memory savings depends on the size of the buffered result set.



 楼主| 发表于 2011-8-4 15:23:52 | 显示全部楼层
Shown below are the simplified behind-the-scenes actions of ext/mysqli with libmysql and ext/mysqli with mysqlnd when mysqli sends a query:

ext/mysqli with libmysql

   

  • mysqli sends a query.
  • Result set gets fetched into libmysql buffers.
  • mysqli allocates zvals, then new buffers.
  • mysqli copies data from libmysql to its own buffers.
  • mysqli calls mysql_free_result() and deallocates libmysql buffers.


ext/mysqli with mysqlnd

   

  • mysqli sends a query.
  • Result set gets fetched row by row -- every row is a different buffer.
  • mysqlnd creates a result set of zvals pointing to the buffers.
  • mysqli calls mysqlnd_free_result() (which could be lightweight) and deallocates the row buffers.

In short, ext/mysqli with libmysql does the following, when compared to ext/mysqli with mysqlnd:
  • One extra allocation for mysqli buffers
  • One extra data copy
  • One extra zval allocation (which can be saved with the zval cache)

The New API Call mysqli_fetch_all()



The mysqlnd driver extends the ext/mysqli API with one new method, mysqli_fetch_all(). The mysqli_fetch_all() method fetches all result rows and returns the result set as an associative array, a numeric array, or both. The method signature is shown below for both the procedural as well as the object-oriented style of programming.

Procedural style:

mixed mysqli_fetch_all (mysqli_result $result [, int $resulttype])


Object-oriented style:

mixed mysqli_result::fetch_all ([ int $resulttype])


where $result is a result set identifier returned by mysqli_query(), mysqli_store_result(), or mysqli_use_result(), and $resulttype is an optional constant indicating what type of array should be produced from the current row data. The possible values for this parameter are the constants MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH. Defaults to MYSQLI_NUM.

Because mysqli_fetch_all() returns all the rows as an array in a single step, it can consume more memory than some of its counterparts like mysqli_fetch_array(). The method mysqli_fetch_array() returns one row at a time from the result set, hence it consumes less memory relative to mysqli_fetch_array(). Besides, if you need to iterate over the result set, you might need a foreach() loop, and this approach might be little slower compared to the result set retrieval using mysqli_fetch_array(). Hence consider using mysqli_fetch_all() only in those situations where the fetched result set is sent to another layer for post processing. If you must process the fetched result set in the same layer with the help of iterators, then the benefit of using the mysqli_fetch_all() method might be minimal, if there is any.

Statistical Data Collection


The mysqlnd driver collects a lot of statistics that you can use to tune your application. The mysqlnd driver enhances the ext/mysqli API with three mysqli_get_XX_stats() methods for easy monitoring and to simplify the bottleneck analysis. For example, using a combination of mysqli_get_XX_stats() methods, you can easily identify a script that is opening more database connections than it needs or selecting more rows than it consumes.

Accessing Client Statistics

To access per-process client statistics, call mysqli_get_client_stats() with no arguments. Similarly, to access client statistics per connection, call mysqli_get_connection_stats() with the database connection handle as the argument. Both of these methods return an associated array with the name of the statistic parameter as the key and the corresponding data as the value.

Alternatively, per-process client statistics can be accessed by calling the phpinfo() method.

All the methods mentioned above return statistics, such as bytes_sent and bytes_received, which return the number of bytes sent to and received from the MySQL Server, result_set_queries, which shows the number of queries that generated a result set, and buffered_sets and unbuffered_sets, which show the number of buffered and unbuffered result sets for the queries that generate a result set but are not run as a prepared statement. The rows_fetched_from_server_normal method shows the number of rows that have been fetched from the server using buffered and unbuffered result sets. The rows_buffered_from_client_normal method shows the number of rows fetched from the server and buffered on the client side. The rows_skipped_normal method shows the number of rows generated by the server but not read from the client.

Accessing Zval Cache Statistics

The mysqlnd driver collects statistics from its internal zval cache, which you can access with the help of the mysqli_get_cache_stat() method. This method returns an associative array with the name of the statistic as the key and the corresponding data as the value. The zval cache statistics might be useful to tweak the zval cache-related php.ini settings for better performance.

Sample PHP Script Demonstrating mysqlnd's Features


The following sample PHP script demonstrates how to:
  • Establish persistent connections
  • Use mysqli_fetch_all() to fetch and display the result set
  • Access client, connection, and zval cache statistics using mysqli_get_client_stats(), mysqli_get_connection_stats(), and mysqli_get_cache_stat() methods

 楼主| 发表于 2011-8-4 15:24:59 | 显示全部楼层
The purpose of the sample code is only to illustrate the syntactical use of new features of mysqlnd. The sample code does not represent any real-world scenarios.
  1. bash# cat PHPmysqliClientmysqlnd.php

  2. <?php

  3.         /* create a persistent connection to the MySQL server */
  4.         $cxn = new mysqli("p:localhost", "root", "admin", "test", 3306, "/tmp/mysql.sock")
  5.                 or die ('Could not connect to the database server' . mysqli_connect_error());

  6.         $query = "SELECT * FROM City";
  7.        
  8.         /* execute the query */
  9.         if ($cxn->real_query ($query)) {

  10.                 /* initiate the result set retrieval */
  11.                 if ($result = $cxn->store_result()) {

  12.                         /* find the number of rows in the result set */
  13.                         $nrows = $result->num_rows;

  14.                         echo "\nRetrieved $nrows row(s).\n\n";
  15.                         echo "CityName\n--------\n";

  16.                         $all_rows = $result->fetch_all(MYSQLI_ASSOC);

  17.                         for($i = 0; $i < count($all_rows); $i++) {
  18.                                 echo $all_rows[$i][CityName] . "\n";
  19.                         }
  20.                 }

  21.                 /* close the result set */
  22.                 $result->close();
  23.         }

  24.         echo "\n\nClient Statistics After One Query\n---------------------------------";
  25.         $client_stats = mysqli_get_client_stats();
  26.         #var_dump($client_stats);
  27.         foreach ($client_stats as $key=>$value) {
  28.                 if ($value > 0) {
  29.                                echo "\n$key : $value";
  30.                 }
  31.         }

  32.         echo "\n\nStatistics for Connection #1\n----------------------------";
  33.         $conn_stats = mysqli_get_connection_stats($cxn);
  34.         #var_dump($conn_stats);
  35.         foreach ($conn_stats as $key=>$value) {
  36.                 if ($value > 0) {
  37.                                echo "\n$key : $value";
  38.                 }
  39.         }

  40.         echo "\n\nCache Statistics After One Query\n--------------------------------";
  41.         $cache_stats = mysqli_get_cache_stats();
  42.         #var_dump($cache_stats);
  43.         foreach ($cache_stats as $key=>$value) {
  44.                 if ($value > 0) {
  45.                                echo "\n$key : $value";
  46.                 }
  47.         }

  48.         echo "\n\n=================================\n\n";
  49.         echo "\nEstablishing connection #2 to the MySQL server ..\n\n";

  50.         /* create a non-persistent connection to the MySQL server */
  51.         $cxn2 = new mysqli("localhost", "root", "admin", "mysql", 3306, "/tmp/mysql.sock")
  52.                 or die ('Could not connect to the database server' . mysqli_connect_error());

  53.         $query = "SELECT Host, User FROM user";

  54.         /* execute the query */
  55.         if ($cxn2->real_query ($query)) {

  56.                 /* initiate the result set retrieval */
  57.                 if ($result = $cxn2->store_result()) {

  58.                         /* find the number of rows in the result set */
  59.                         $nrows = $result->num_rows;
  60.                         echo "\nRetrieved $nrows row(s).\n\n";

  61.                         echo "Host\t\tUser\n----\t\t----\n";

  62.                         $all_rows = $result->fetch_all(MYSQLI_ASSOC);

  63.                         for($i = 0; $i < count($all_rows); $i++) {
  64.                                 echo $all_rows[$i][Host] . "\t" . $all_rows[$i][User] . "\n";
  65.                         }
  66.                 }

  67.                 /* close the result set */
  68.                 $result->close();
  69.         }

  70.         echo "\n\nClient Statistics After Two Queries\n-----------------------------------";
  71.         $client_stats = mysqli_get_client_stats();
  72.         #var_dump($client_stats);
  73.         foreach ($client_stats as $key=>$value) {
  74.                 if ($value > 0) {
  75.                         echo "\n$key : $value";
  76.                 }
  77.         }

  78.         echo "\n\nStatistics for Connection #2\n----------------------------";
  79.         $conn_stats = mysqli_get_connection_stats($cxn2);
  80.         #var_dump($conn_stats);
  81.         foreach ($conn_stats as $key=>$value) {
  82.                 if ($value > 0) {
  83.                         echo "\n$key : $value";
  84.                 }
  85.         }

  86.         echo "\n\nCache Statistics After Two Queries\n----------------------------------";
  87.         $cache_stats = mysqli_get_cache_stats();
  88.         #var_dump($cache_stats);
  89.         foreach ($cache_stats as $key=>$value) {
  90.                 if ($value > 0) {
  91.                         echo "\n$key : $value";
  92.                 }
  93.         }

  94.         echo "\n";

  95.         //phpinfo();

  96.         /* close the database connections */
  97.         $cxn->close();
  98.         $cxn2->close();
  99. ?>

  100. bash# /export/home/php53/bin/php PHPmysqliClientmysqlnd.php

  101. Retrieved 3 row(s).

  102. CityName
  103. --------
  104. Hyderabad, India
  105. San Francisco, USA
  106. Sydney, Australia


  107. Client Statistics After One Query
  108. ---------------------------------
  109. bytes_sent : 90
  110. bytes_received : 222
  111. packets_sent : 2
  112. packets_received : 9
  113. protocol_overhead_in : 36
  114. protocol_overhead_out : 8
  115. bytes_received_ok_packet : 11
  116. bytes_received_eof_packet : 9
  117. bytes_received_rset_header_packet : 5
  118. bytes_received_rset_field_meta_packet : 54
  119. bytes_received_rset_row_packet : 70
  120. packets_sent_command : 1
  121. packets_received_ok : 1
  122. packets_received_eof : 1
  123. packets_received_rset_header : 1
  124. packets_received_rset_field_meta : 1
  125. packets_received_rset_row : 4
  126. result_set_queries : 1
  127. buffered_sets : 1
  128. rows_fetched_from_server_normal : 3
  129. rows_buffered_from_client_normal : 3
  130. rows_fetched_from_client_normal_buffered : 3
  131. rows_skipped_normal : 3
  132. copy_on_write_performed : 3
  133. connect_success : 1
  134. active_connections : 1
  135. active_persistent_connections : 1
  136. explicit_free_result : 1
  137. mem_erealloc_count : 1
  138. mem_efree_count : 2
  139. mem_realloc_count : 1
  140. proto_text_fetched_string : 3

  141. Statistics for Connection #1
  142. ----------------------------
  143. bytes_sent : 90
  144. bytes_received : 222
  145. packets_sent : 2
  146. packets_received : 9
  147. protocol_overhead_in : 36
  148. protocol_overhead_out : 8
  149. bytes_received_ok_packet : 11
  150. bytes_received_eof_packet : 9
  151. bytes_received_rset_header_packet : 5
  152. bytes_received_rset_field_meta_packet : 54
  153. bytes_received_rset_row_packet : 70
  154. packets_sent_command : 1
  155. packets_received_ok : 1
  156. packets_received_eof : 1
  157. packets_received_rset_header : 1
  158. packets_received_rset_field_meta : 1
  159. packets_received_rset_row : 4
  160. result_set_queries : 1
  161. buffered_sets : 1
  162. rows_fetched_from_server_normal : 3
  163. rows_buffered_from_client_normal : 3
  164. rows_skipped_normal : 3
  165. connect_success : 1
  166. active_connections : 1
  167. active_persistent_connections : 1
  168. explicit_free_result : 1
  169. proto_text_fetched_string : 3

  170. Cache Statistics After One Query
  171. --------------------------------
  172. put_misses : 3
  173. get_hits : 3
  174. size : 2000
  175. free_items : 1997
  176. references : 3

  177. =================================


  178. Establishing connection #2 to the MySQL server ..


  179. Retrieved 5 row(s).

  180. Host                User
  181. ----                ----
  182. 127.0.0.1        root
  183. localhost       
  184. localhost        root
  185. unknown       
  186. unknown        root


  187. Client Statistics After Two Queries
  188. -----------------------------------
  189. bytes_sent : 190
  190. bytes_received : 501
  191. packets_sent : 4
  192. packets_received : 21
  193. protocol_overhead_in : 84
  194. protocol_overhead_out : 16
  195. bytes_received_ok_packet : 22
  196. bytes_received_eof_packet : 18
  197. bytes_received_rset_header_packet : 10
  198. bytes_received_rset_field_meta_packet : 148
  199. bytes_received_rset_row_packet : 157
  200. packets_sent_command : 2
  201. packets_received_ok : 2
  202. packets_received_eof : 2
  203. packets_received_rset_header : 2
  204. packets_received_rset_field_meta : 3
  205. packets_received_rset_row : 10
  206. result_set_queries : 2
  207. buffered_sets : 2
  208. rows_fetched_from_server_normal : 8
  209. rows_buffered_from_client_normal : 8
  210. rows_fetched_from_client_normal_buffered : 8
  211. rows_skipped_normal : 8
  212. copy_on_write_performed : 13
  213. connect_success : 2
  214. active_connections : 2
  215. active_persistent_connections : 1
  216. explicit_free_result : 2
  217. mem_erealloc_count : 1
  218. mem_efree_count : 2
  219. mem_realloc_count : 4
  220. proto_text_fetched_string : 13

  221. Statistics for Connection #2
  222. ----------------------------
  223. bytes_sent : 100
  224. bytes_received : 279
  225. packets_sent : 2
  226. packets_received : 12
  227. protocol_overhead_in : 48
  228. protocol_overhead_out : 8
  229. bytes_received_ok_packet : 11
  230. bytes_received_eof_packet : 9
  231. bytes_received_rset_header_packet : 5
  232. bytes_received_rset_field_meta_packet : 94
  233. bytes_received_rset_row_packet : 87
  234. packets_sent_command : 1
  235. packets_received_ok : 1
  236. packets_received_eof : 1
  237. packets_received_rset_header : 1
  238. packets_received_rset_field_meta : 2
  239. packets_received_rset_row : 6
  240. result_set_queries : 1
  241. buffered_sets : 1
  242. rows_fetched_from_server_normal : 5
  243. rows_buffered_from_client_normal : 5
  244. rows_skipped_normal : 5
  245. connect_success : 1
  246. active_connections : 1
  247. explicit_free_result : 1
  248. proto_text_fetched_string : 10

  249. Cache Statistics After Two Queries
  250. ----------------------------------
  251. put_misses : 13
  252. get_hits : 13
  253. size : 2000
  254. free_items : 1987
  255. references : 4
复制代码

Be aware that some of the experimental functions that are available with ext/mysqli and libmysql are not available with ext/mysqli and mysqlnd, for example, mysqli_embedded_*() and mysqli_*rpl*_().

 楼主| 发表于 2011-8-4 15:26:30 | 显示全部楼层
Explore Other Tutorials in This Series


To find out more about Developing MySQL Database Applications With PHP, see all tutorials in the series:

For More Information




Acknowledgments
Ulf Wendel, Sun | MySQL AB

发表于 2011-10-30 12:22:58 | 显示全部楼层
看过,的确不错。谢谢楼主
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )

GMT-8, 2026-4-10 01:46 , Processed in 0.024323 second(s), 15 queries .

Supported by Weloment Group X3.5

© 2008-2026 Best Deal Online

快速回复 返回顶部 返回列表