Quickstart and Examples
The mysqlnd user handler plugin can be understood as a client-side proxy
for all PHP MySQL extensions (mysqli,
mysql,
PDO_MYSQL), if they are compiled to
use the mysqlnd library. The
extensions use the mysqlnd library internally, at the C
level, to communicate with the MySQL server. PECL/mysqlnd_uh
allows it to hook many mysqlnd calls. Therefore,
most activities of the PHP MySQL extensions can be monitored.
Because monitoring happens at the level of the library, at a layer below the
application, it is possible to monitor applications without changing them.
On the C level, the mysqlnd library is structured in modules
or classes. The extension hooks almost all methods of the mysqlnd
internal connection class and exposes them through the
user space class MysqlndUhConnection. Some few methods of
the mysqlnd internal statement class are made available
to the PHP user with the class MysqlndUhPreparedStatement.
By subclassing the classes MysqlndUhConnection and
MysqlndUhPreparedStatement users get access to
mysqlnd internal function calls.
The internal mysqlnd function calls are not designed
to be exposed to the PHP user. Manipulating their activities may
cause PHP to crash or leak memory. Often, this is not considered a bug. Please,
keep in mind that you are accessing C library functions through
PHP which are expected to take certain actions, which you may not be able to
emulate in user space. Therefore, it is strongly recommended to always call
the parent method implementation when subclassing MysqlndUhConnection
or MysqlndUhPreparedStatement. To prevent the worst
case, the extension performs some sanity checks. Please, see also the
Mysqlnd_uh &ConfigureOptions;.
Setup
The plugin is implemented as a PHP extension. See the
installation instructions to
install the
PECL/mysqlnd_uh extension.
Then, load the extension into PHP and activate the plugin in the PHP configuration
file using the PHP configuration directive named
mysqlnd_uh.enable.
The below example shows the default settings of the extension.
Enabling the plugin (php.ini)How it works
This describes the background and inner workings of the mysqlnd_uh
extension.
Two classes are provided by the extension: MysqlndUhConnection
and MysqlndUhPreparedStatement. MysqlndUhConnection lets
you access almost all methods of the mysqlnd
internal connection class. The latter exposes some selected
methods of the mysqlnd internal statement class.
For example, MysqlndUhConnection::connect maps to
the mysqlnd library C function
mysqlnd_conn__connect.
As a mysqlnd plugin, the PECL/mysqlnd_uh extension replaces mysqlnd
library C functions with its own functions. Whenever a
PHP MySQL extension compiled to use mysqlnd calls
a mysqlnd function, the functions installed by the plugin are executed
instead of the original mysqlnd ones. For example,
mysqli_connect invokes mysqlnd_conn__connect,
so the connect function installed by PECL/mysqlnd_uh will be called.
The functions installed by PECL/mysqlnd_uh are the methods of the built-in classes.
The built-in PHP classes and their methods do nothing but call their
mysqlnd C library counterparts, to behave exactly
like the original mysqlnd function they replace.
The code below illustrates in pseudo-code what the extension does.
Pseudo-code: what a built-in class does
The build-in classes behave like a transparent proxy. It is possible for
you to replace the proxy with your own. This is done by subclassing
MysqlndUhConnection or
MysqlndUhPreparedStatement to extend the functionality
of the proxy, followed by registering a new proxy object.
Proxy objects are installed by
mysqlnd_uh_set_connection_proxy
and
mysqlnd_uh_set_statement_proxy.
Installing a proxy
]]>
&example.outputs;
NULL,
1 => 'localhost',
2 => 'root',
3 => '',
4 => 'test',
5 => 3306,
6 => NULL,
7 => 131072,
))
proxy::connect returns true
]]>
Installing a proxy
The extension provides two built-in classes: MysqlndUhConnection
and MysqlndUhPreparedStatement. The classes are used
for hooking mysqlnd library calls. Their methods correspond
to mysqlnd internal functions. By default they act like
a transparent proxy and do nothing but call their mysqlnd counterparts.
By subclassing the classes you can install your own proxy to monitor mysqlnd.
See also the How it works
guide to learn about the inner workings of this extension.
Connection proxies are objects of the type MysqlndUhConnection.
Connection proxy objects are installed by
mysqlnd_uh_set_connection_proxy.
If you install the built-in class MysqlndUhConnection
as a proxy, nothing happens. It behaves like a transparent proxy.
Proxy registration, mysqlnd_uh.enable=1
]]>
The PHP_INI_SYSTEM configuration setting
mysqlnd_uh.enable
controls whether a proxy may be set. If disabled, the extension
will throw errors of type E_WARNINGProxy installation disabled
]]>
&example.outputs;
To monitor mysqlnd, you have to write your own
proxy object subclassing MysqlndUhConnection.
Please, see the function reference for a the list of methods that
can be subclassed. Alternatively, you can use reflection to inspect
the built-in MysqlndUhConnection.
Create a new class proxy. Derive it from the
built-in class MysqlndUhConnection.
Replace the
MysqlndUhConnection::connect.
method. Print out the host parameter value passed to the method.
Make sure that you call the parent implementation of the connect
method. Failing to do so may give unexpected and undesired results, including
memory leaks and crashes.
Register your proxy and open three connections using the PHP MySQL
extensions mysqli,
mysql,
PDO_MYSQL. If the extensions have been
compiled to use the mysqlnd library, the
proxy::connect method will be called three times, once
for each connection opened.
Connection proxy
]]>
&example.outputs;
The use of prepared statement proxies follows the same pattern: create a
proxy object of the type MysqlndUhPreparedStatement
and install the proxy using
mysqlnd_uh_set_statement_proxy.
Prepared statement proxy
prepare("SELECT 'mysqlnd hacking made easy' AS _msg FROM DUAL");
?>
]]>
&example.outputs;
Basic query monitoring
Basic monitoring of a query statement is easy with PECL/mysqlnd_uh.
Combined with debug_print_backtrace it can become a powerful
tool, for example, to find the origin of certain statement. This may
be desired when searching for slow queries but also after database
refactoring to find code still accessing deprecated databases or
tables. The latter may be a complicated matter to do otherwise, especially if
the application uses auto-generated queries.
Basic Monitoring
query("SELECT 1 AS _one FROM DUAL")->fetchAll(PDO::FETCH_ASSOC));
$mysqli = new mysqli("localhost", "root", "", "test");
$mysqli->prepare("SELECT 1 AS _two FROM DUAL");
?>
]]>
&example.outputs;
query(Resource id #19, SELECT 1 AS _one FROM DUAL)
#1 PDO->query(SELECT 1 AS _one FROM DUAL) called at [example.php:19]
array(1) {
[0]=>
array(1) {
["_one"]=>
string(1) "1"
}
}
#0 stmt_proxy->prepare(Resource id #753, SELECT 1 AS _two FROM DUAL)
#1 mysqli->prepare(SELECT 1 AS _two FROM DUAL) called at [example.php:22]
]]>
For basic query monitoring you should install a connection and a prepared statement
proxy. The connection proxy should subclass MysqlndUhConnection::query.
All database queries not using native prepared statements will call this method.
In the example the query function is invoked by a PDO call.
By default, PDO_MySQL is using prepared statement emulation.
All native prepared statements are prepared with the prepare
method of mysqlnd exported through
MysqlndUhPreparedStatement::prepare. Subclass
MysqlndUhPreparedStatement and overwrite prepare
for native prepared statement monitoring.