diff --git a/reference/mysqlnd_ms/book.xml b/reference/mysqlnd_ms/book.xml new file mode 100755 index 0000000000..de3fdba452 --- /dev/null +++ b/reference/mysqlnd_ms/book.xml @@ -0,0 +1,211 @@ + + + + + Mysqlnd replication and load balancing plugin + mysqlnd_ms + + + &reftitle.intro; + + The mysqlnd replication and load balancing plugin (mysqlnd_ms) + adds easy to use MySQL replication support to all PHP MySQL extensions that use + mysqlnd. + + + As of version PHP 5.3.3 the MySQL native driver for PHP + (mysqlnd) + features an internal plugin C API. C plugins, such as the replication and + load balancing plugin, can extend the functionality of + mysqlnd. + + + The MySQL native driver for PHP is a C library which ships together with + PHP as of PHP 5.3.0. It serves as a drop-in replacement for the + MySQL Client Library (AKA libmysql/libmysqlclient). Using mysqlnd has + several advantages: no extra downloads because it comes with PHP, + PHP license, lower memory consumption in certain cases, + new functionality such as asynchronous queries. + + + Mysqlnd plugins such as the replication and load balancing plugin operate + mostly transparent from an user perspective. The replication and load balancing + plugin supports all PHP applications + and all PHP MySQL extensions ( + mysqli, + mysql, + PDO_MYSQL). + It does not change existing APIs. Therefore, it can easily be used with + existing PHP applications. + + + + The mysqlnd replication and load balancing plugin is in alpha status. + It is not feature complete. + + +
+ Key Features + + + + + Transparent and therefore easy to use + + + + + + supports all PHP MySQL extensions + + + + + no API changes + + + + + very little, if any, application changes required, dependent on the usage scenario required + + + + + + + + + Featured read-write split strategies + + + + + + Automatic detection of SELECT, supports SQL hints to overrule automatism + + + + + user-defined + + + + + + + + + Featured load balancing strategies + + + + + + Round Robin: choose different slave in round robin fashion for every slave request. + + + + + Random: choose random slave for every slave request. + + + + + Random once (sticky): choose random slave once to run all slave requests for the duration of a web request. + + + + + User-defined. The application can register callbacks with mysqlnd_ms. + + + + + + + +
+ +
+ Limitations + + The plugin does not support MySQL replication setups with more + than one master server. + + + The built-in read/write-split mechanism is very basic. Every + query which starts with SELECT + is considered a read request to be sent to a MySQL slave server. + All other queries, including, for example, SHOW + statements, are considered as write requests to be sent to the MySQL master server. + The build-in behaviour can be overruled using + SQL hints or an user-defined + callback function. + + + The read/write splitter is not aware of multi-statements. Multi-statements + are considered as one statement. The decision of where to run the statement + will be based on the beginning of the statement string. + + + The plugin does not support native prepared statements. Please + note that PDO_MySQL is using a + client-side prepared statement emulation by default. Client-side emulated + prepared statements are fully supported by the replication and load balancing + plugin because the emulation is not using native prepared statements. + If you are using PHP based database abstraction, please consult the + vendor manual to learn if a client-side prepared statement emulation is + used. + + + + Application must be aware of the consequences of connection switches performed + for load balancing purpose. Please check the documentation on + connection pooling and switching, + transaction handling, + failover + load balancing and + read-write splitting carefully. + + +
+ +
+ On the name + + The shortcut mysqlnd_ms + stands for mysqlnd master slave plugin. The name + was choosen for a quick-and-dirty proof-of-concept. In the beginning + the developers did not expect to continue using the code base. + +
+
+ + &reference.mysqlnd-ms.quickstart; + &reference.mysqlnd-ms.concepts; + &reference.mysqlnd-ms.setup; + &reference.mysqlnd-ms.constants; + &reference.mysqlnd-ms.reference; + +
+ + diff --git a/reference/mysqlnd_ms/concepts.xml b/reference/mysqlnd_ms/concepts.xml new file mode 100755 index 0000000000..41440a127a --- /dev/null +++ b/reference/mysqlnd_ms/concepts.xml @@ -0,0 +1,302 @@ + + + + + Concepts +
+ Architecture + + The mysqlnd replication and load balancing plugin is + implemented as a PHP extension. + It is written in C and operates under the hood of PHP. During the + startup of the PHP interpreter, in the module init phase of the + PHP engine, it gets registered as a + mysqlnd plugin to replace selected + mysqlnd C methods. + + + At PHP run time it inspects queries send from + mysqlnd (PHP) to the MySQL server. If a query is recognized as read-only + it will be sent to one of the configured slave servers. Statements are + considered read-only if they either start with SELECT, + the SQL hint /*ms=slave*/ or a slave had been choose for + running the previous query and the query starts with the SQL hint + /*ms=last_used*/. In all other cases the query will + be sent to the MySQL replication master server. + + + The plugin takes care internally of opening and closing the database connections + to the master server and the slave servers. From an application + point of view there continues to be only one connection handle. However, + internally, this one public connection handle represents a pool of + internal connections managed by the plugin. The plugin proxies queries + to the master server and the slave ones using multiple connections. + + + Database connections have a state consisting, for example, transaction + status, transaction settings, character set settings, temporary tables. + The plugin will try to maintain the same state among all internal + connections, whenever this can be done in an automatic and transparent way. + In cases where it is not easily possible to maintain state among all + connections, such as when using BEGIN TRANSACTION, the + plugin leaves it to the user to handle. Please, find further details below. + + +
+ +
+ Connection pooling and switching + + The replication and load balancing plugin changes the semantics of a PHP + MySQL connection handle. The existing API of the PHP MySQL extensions + (mysqli, + mysql, + PDO_MYSQL) are not changed in + a way that functions are added or removed. But their behaviour + changes when using the plugin. Existing applications do not need to + be adapted to a new API. But they may need to be modified because of + the behaviour changes. + + + The plugin breaks the one-by-one relationship between a + mysqli, + mysql, + PDO_MYSQL connection + handle and a MySQL wire connection. If using the plugin a + mysqli, + mysql, + PDO_MYSQL connection + handle represents a local pool of connections to the configured + MySQL replication master and the MySQL replication slave servers. + The plugin redirects queries to the master and slave servers. + At some point in time one and the same PHP connection handle + may point to the MySQL master server. Later on, it may point + to one of the slave servers or still the master. Manipulating + and replacing the wire connection referenced by a PHP MySQL + connection handle is not a transparent operation. + + + Every MySQL connection has a state. The state of the connections in + the connection pool of the plugin can differ. Whenever the + plugin switches from one wire connection to another, the current state of + the user connection may change. The applications must be aware of this. + + + The following listshows what the connection state consists of. + + + + + + Transaction status + + + + + Temporary tables + + + + + Table locks + + + + + Session system variables and session user variables + + + + + Session system variables and session user variables + + + + + Prepared statements + + + + + HANDLER variables + + + + + Locks acquired with GET_LOCK() + + + + + + The plugins philosophy is to align the state of connections in the + pool only if the state is under full control of the plugin, or if it is + necessary for security reasons. Just a few actions that change the + state of the connection fall into this category. The plugin does broadcast + the following state changing client calls to all currently open + connections in the connection pool: change_user, + select_db, set_charset, + set_server_option, set_client_option, + autocommit. + + + The plugin does not proxy or + remember settings to apply them on connections + opened in the future. This is important to remember, if + using + lazy connections. + Lazy connections are connections which are not + opened before the client sends the first connection. + Use of lazy connections is the default plugin action. + + + Connection switches happen right before queries are run. The plugin does + not switch the current connection until the moment in time when + the next statement is executed. + + + Please, do not miss the MySQL reference manual chapter on + replication features and issues. Some restrictions you hit may not be related + to the PHP plugin but are properties of the MySQL replication system. + +
+ +
+ Transaction handling + + Transaction handling is fundamentally changed. + A SQL transaction is a unit of work run on one database server. The + unit of work consists of one or more SQL statements. + + + By default the plugin is not aware of SQL transactions. The plugin may + switch connections for load balancing at any point in time. Connection + switches may happen in the middle of a transaction. This is against the + nature of a SQL transaction. By default the plugin is not transaction safe. + + + At the time of writing, applications using SQL transactions together with + the plugin must use SQL hints to disable connection switches in the middle + of a SQL transaction. Please, find details in the examples section. + + + Future versions of the plugin might offer special settings to make + plugin transaction safe. + +
+ +
+ Failover + + Connection failover handling is left to the user. The application is responsible + for checking return values of the database functions it calls and reacting + to possible errors. If, for example, the plugin recognizes a query as a read-only + query to be sent to the slave servers and the slave server selected by the + plugin is not available, the plugin will raise an error after not executing + the statement. + + + It is up to + the application to handle the error and, if need be, re-issue the query to + trigger selection of another slave server for statement execution. The plugin + will make no attempts to failover automatically because the plugin + cannot ensure that an automatic failover will not change the state of + the connection. For example, the application may have issued a query + which depends on SQL user variables which are bound to a specific connection. + Such a query might return wrong results if the plugin would switch the + connection implicitly as part of automatic failover. To ensure correct + results the application must take care of the failover and rebuild + the required connection state. Therefore, by default, no automatic failover + is done by the plugin. + + + An user who does not change the connection state after opening a connection + may activate automatic master failover. + + + The failover policy is configured in the plugins configuration file by help + of the + failover + configuration directive. + +
+ +
+ Load balancing + + Four load balancing strategies are supported to distribute read-only + statements over the configured MySQL slave servers: + random, random_once (default), + roundrobin, user. + + + The load balancing policy is configured in the plugins configuration + file using the + pick[] + configuration directive. + +
+ + +
+ Read-write splitting + + The plugin runs read-only statements on the configured MySQL slaves and + all other queries on the MySQL master. Statements are + considered read-only if they either start with SELECT, + the SQL hint /*ms=slave*/ or a slave had been chosen for + running the previous query and the query starts with the SQL hint + /*ms=last_used*/. In all other cases the query will + be send to the MySQL replication master server. + + + SQL hints are a special kind of standard compliant SQL comments. The plugin + does check every statement for certain SQL hints. The SQL hints are described + together with the constants + exported by the extension. Other systems + involved in the statement processing, such as the MySQL server, SQL firewalls + or SQL proxies are unaffected by the SQL hints because those systems are + supposed to ignore SQL comments. + + + The built-in read-write splitter can be replaced by a user-defined one, see also + mysqlnd_ms_set_user_pick_server. + + + A user-defined read-write splitter can ask the built-in logic to make + a proposal where to sent a statement by invoking + mysqlnd_ms_is_select. + + + + The built-in read-write splitter is not aware of multi-statements. + Multi-statements are seen as one statement. The splitter will check the + beginning of the statement to decide where to run the statement. If, for example, + a multi-statement begins with + SELECT 1 FROM DUAL; INSERT INTO test(id) VALUES (1); ... + the plugin will run it on a slave although the statement is not read-only. + + +
+
+ + diff --git a/reference/mysqlnd_ms/configure.xml b/reference/mysqlnd_ms/configure.xml new file mode 100755 index 0000000000..a41090e1ac --- /dev/null +++ b/reference/mysqlnd_ms/configure.xml @@ -0,0 +1,49 @@ + + + +
+ &reftitle.install; + + + + The mysqlnd replication and load balancing plugin is in alpha status. + It is not feature complete. + + + + + &pecl.moved; + + + + &pecl.info; + &url.pecl.package;mysqlnd_ms + + + + &pecl.windows.download; + + +
+ + + diff --git a/reference/mysqlnd_ms/constants.xml b/reference/mysqlnd_ms/constants.xml new file mode 100755 index 0000000000..7000eca4b7 --- /dev/null +++ b/reference/mysqlnd_ms/constants.xml @@ -0,0 +1,246 @@ + + + + + &reftitle.constants; + &extension.constants; + + + SQL hint related + + + + + The mysqlnd replication and load balancing plugin (mysqlnd_ms) + does read/write splitting to direct write queries to a MySQL master server and + read-only queries to MySQL slave servers in a MySQL replication setup. + The plugin has a built-in read/write split logic. The logic is very basic. + All queries which start with SELECT are considered read-only + queries which shall be send to a MySQL slave server listed in + the plugin configuration file. All other queries shall be directed to the + MySQL master server specified in the plugin configuration file. + + + User supplied SQL hints can be used to overrule automatic read/write splitting + to gain full control on the process. SQL hints are standards compliant + SQL comments. The plugin will scan the beginning of a query string for + a SQL comment with certain contents which control query redirection. + Other systems involved in the query processing are unaffected by the + plugins SQL hints because other systems will ignore the SQL comments. + + + The plugin supports three SQL hints to direct queries to the MySQL slave + servers, the MySQL master server and the last used MySQL server. SQL hints + must be placed at the beginning to be recognized by the plugin. + + + It is recommended to use the string constants + MYSQLND_MS_MASTER_SWITCH, + MYSQLND_MS_SLAVE_SWITCH and + MYSQLND_MS_LAST_USED_SWITCH instead of their literal + values for better portability. + + + +]]> + + &examples.outputs; + + + + + + + + + + MYSQLND_MS_MASTER_SWITCH + (string) + + + + SQL hint used to send a query to the MySQL replication master server. + + + + + + MYSQLND_MS_SLAVE_SWITCH + (string) + + + + SQL hint used to send a query to one of the MySQL replication slave servers. + + + + + + MYSQLND_MS_LAST_USED_SWITCH + (string) + + + + SQL hint used to send a query to the last used MySQL server. The last + used MySQL server can either be a master or a slave server in a + MySQL replication setup. + + + + + + + + mysqlnd_ms_is_select related + + + + + + MYSQLND_MS_QUERY_USE_MASTER + (integer) + + + + If mysqlnd_ms_is_select returns + MYSQLND_MS_QUERY_USE_MASTER for a given query, the + built-in read/write split mechanism recommends sending the query to + a MySQL replication master server. + + + + + + MYSQLND_MS_QUERY_USE_SLAVE + (integer) + + + + If mysqlnd_ms_is_select returns + MYSQLND_MS_QUERY_USE_SLAVE for a given query, the + built-in read/write split mechanism recommends sending the query to + a MySQL replication slave server. + + + + + + MYSQLND_MS_QUERY_USE_LAST_USED + (integer) + + + + If mysqlnd_ms_is_select returns + MYSQLND_MS_QUERY_USE_LAST_USED for a given query, the + built-in read/write split mechanism recommends sending the query to + the last used server. + + + + + + + + Other + + + The plugins version number can be obtained using + MYSQLND_MS_VERSION or + MYSQLND_MS_VERSION_ID. + MYSQLND_MS_VERSION + is the string representation of the numerical version number + MYSQLND_MS_VERSION_ID, which is an integer such as 10000. + Developers can calculate the version number as follows. + + + + + + + Version (part) + Example + + + + + Major*10000 + 1*10000 = 10000 + + + Minor*100 + 0*100 = 0 + + + Patch + 0 = 0 + + + MYSQLND_MS_VERSION_ID + 10000 + + + + + + + + + + MYSQLND_MS_VERSION + (string) + + + + Plugin version string, for example, 1.0.0-prototype. + + + + + + MYSQLND_MS_VERSION_ID + (integer) + + + + Plugin version number, for example, 10000. + + + + + + + + + diff --git a/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml b/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml new file mode 100755 index 0000000000..63b2d30c8a --- /dev/null +++ b/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml @@ -0,0 +1,345 @@ + + + + + + mysqlnd_ms_get_stats + Returns query distribution and connection statistics + + + + &reftitle.description; + + array + mysqlnd_ms_get-stats + + + + Returns an array of statistics collected by the replication + and load balancing plugin. + + + The PHP configuration setting + mysqlnd_ms.collect_statistics + controls the collection of statistics. The collection of statistics + is disabled by default for performance reasons. + + + The scope of the statistics is the + PHP process. + Depending on your deployment model a + PHP process may handle one or multiple requests. + + + Statistics are aggregated for connections. It is not possible + to tell how much queries originating from + mysqli, + PDO_MySQL or + mysql API calls have + contributed to the aggregated data values. + + + + + &reftitle.parameters; + &no.function.parameters; + + + + &reftitle.returnvalues; + + Returns NULL if the + the PHP configuration directive + mysqlnd_ms.enable + has disabled the plugin. Otherwise, returns array of statistics. + + + Array of statistics + + + + + + + + + Statistic + Description + Version + + + + + + use_slave + + + Number of statements considered as read-only by the built-in query analyzer. + Neither statements which begin with a SQL hint to force + use of slave nor statements directed to a slave by an user-defined + callback are included. The total number of statements sent to the slaves is + use_slave + use_slave_sql_hint + + use_slave_callback. + + Since 1.0.0. + + + + use_master + + + Number of statements not considered as read-only by the built-in query analyzer. + Neither statements which begin with a SQL hint to force + use of master nor statements directed to a master by an user-defined + callback are included. The total number of statements sent to the master is + use_master + use_master_sql_hint + + use_master_callback. + + Since 1.0.0. + + + + use_slave_sql_hint + + + Number of statements sent to a slave because statement begins with + the SQL hint to force use of slave. + + Since 1.0.0. + + + + use_master_sql_hint + + + Number of statements sent to a master because statement begins with + the SQL hint to force use of master. + + Since 1.0.0. + + + + use_last_used_sql_hint + + + Number of statements sent to server which has run the previous statement, + because statement begins with the SQL hint to force use of previously + used server. + + Since 1.0.0. + + + + use_slave_callback + + + Number of statements sent to a slave because an user-defined callback + has chosen a slave server for statement execution. + + Since 1.0.0. + + + + use_master_callback + + + Number of statements sent to a master because an user-defined callback + has chosen a master server for statement execution. + + Since 1.0.0. + + + + non_lazy_connections_slave_success + + + Number of successfully opened slave connections from + configurations not using + lazy connections. + The total number of successfully opened slave connections + is non_lazy_connections_slave_success + + lazy_connections_slave_success + + Since 1.0.0. + + + + non_lazy_connections_slave_failed + + + Number of failed slave connection attempts from + configurations not using + lazy connections. + The total number of failed slave connection attempts + is non_lazy_connections_slave_failed + + lazy_connections_slave_failed + + Since 1.0.0. + + + + non_lazy_connections_master_success + + + Number of successfully opened master connections from + configurations not using + lazy connections. + The total number of successfully opened master connections + is non_lazy_connections_master_success + + lazy_connections_master_success + + Since 1.0.0. + + + + non_lazy_connections_master_failed + + + Number of failed master connection attempts from + configurations not using + lazy connections. + The total number of failed master connection attempts + is non_lazy_connections_master_failed + + lazy_connections_master_failed + + Since 1.0.0. + + + + lazy_connections_slave_success + + + Number of successfully opened slave connections from + configurations using + lazy connections. + + Since 1.0.0. + + + + lazy_connections_slave_failed + + + Number of failed slave connection attempts from + configurations using + lazy connections. + + Since 1.0.0. + + + + lazy_connections_master_success + + + Number of successfully opened master connections from + configurations using + lazy connections. + + Since 1.0.0. + + + + lazy_connections_master_failed + + + Number of failed master connection attempts from + configurations using + lazy connections. + + Since 1.0.0. + + + + + + + + &reftitle.examples; + + + <function>mysqlnd_ms_get_stats</function> example + + +]]> + + &example.outputs; + + + string(1) "0" + ["use_master"]=> + string(1) "0" + ["use_slave_forced"]=> + string(1) "0" + ["use_master_forced"]=> + string(1) "0" + ["use_last_used_forced"]=> + string(1) "0" + ["non_lazy_connections_slave_success"]=> + string(1) "0" + ["non_lazy_connections_slave_failure"]=> + string(1) "0" + ["non_lazy_connections_master_success"]=> + string(1) "0" + ["non_lazy_connections_master_failure"]=> + string(1) "0" + ["lazy_connections_slave_success"]=> + string(1) "0" + ["lazy_connections_slave_failure"]=> + string(1) "0" + ["lazy_connections_master_success"]=> + string(1) "0" + ["lazy_connections_master_failure"]=> + string(1) "0" +} +]]> + + + + + + + &reftitle.seealso; + + + + Runtime configuration + + + mysqlnd_ms.collect_statistics + + + mysqlnd_ms.enable + + + + + + + + diff --git a/reference/mysqlnd_ms/functions/mysqlnd-ms-query-is-select.xml b/reference/mysqlnd_ms/functions/mysqlnd-ms-query-is-select.xml new file mode 100755 index 0000000000..65601921b2 --- /dev/null +++ b/reference/mysqlnd_ms/functions/mysqlnd-ms-query-is-select.xml @@ -0,0 +1,139 @@ + + + + + + mysqlnd_ms_query_is_select + Find whether to send the query to the master, the slave or the last used MySQL server + + + + &reftitle.description; + + int + mysqlnd_ms_query_is_select + stringquery + + + Finds whether to send the query to the master, the slave or the + last used MySQL server. + + + The plugins built-in read/write split mechanism + will be used to analyze the query string to make a recommendation where + to send the query. The built-in read/write split mechanism is very + basic and simple. The plugin will recommend sending all queries to the + MySQL replication master server but those which begin with + SELECT, or begin with a SQL hint which + enforces sending the query to a slave server. Due to the basic + but fast algorithm the plugin may propose to run some read-only + statements such as SHOW TABLES on the replication master. + + + + + &reftitle.parameters; + + + query + + + Query string to test. + + + + + + + + &reftitle.returnvalues; + + A return value of MYSQLND_MS_QUERY_USE_MASTER + indicates that the query should be send to the MySQL replication + master server. The function returns a value of + MYSQLND_MS_QUERY_USE_SLAVE if the query can be run + on a slave because it is considered read-only. A value of + MYSQLND_MS_QUERY_USE_LAST_USED is returned to recommend + running the query on the last used server. This can either be a MySQL + replication master server or a MySQL replication slave server. + + + + + &reftitle.examples; + + + <function>mysqlnd_ms_query_is_select</function> example + + +]]> + + &example.outputs; + + + + + + + + + &reftitle.seealso; + + + + Predefined Constants + + + + + + + + diff --git a/reference/mysqlnd_ms/functions/mysqlnd-ms-set-user-pick-server.xml b/reference/mysqlnd_ms/functions/mysqlnd-ms-set-user-pick-server.xml new file mode 100755 index 0000000000..85b6e3f90e --- /dev/null +++ b/reference/mysqlnd_ms/functions/mysqlnd-ms-set-user-pick-server.xml @@ -0,0 +1,228 @@ + + + + + + mysqlnd_ms_set_user_pick_server + Sets a callback for user-defined read/write splitting + + + + &reftitle.description; + + bool + mysqlnd_ms_set_user_pick_server + stringfunction + + + Sets a callback for user-defined read/write splitting. The plugin will + call the callback only if pick[]=user is the default + rule for server picking in the relevant section of the plugins configuration + file. + + + The plugins built-in read/write query split mechanism decisions can be + overwritten in two ways. The easiest way is to prepend the query string + with the SQL hints MYSQLND_MS_MASTER_SWITCH, + MYSQLND_MS_SLAVE_SWITCH or + MYSQLND_MS_LAST_USED_SWITCH. Using SQL hints one can + control, for example, whether a query shall be send to the MySQL replication + master server or one of the slave servers. By help of SQL hints it is + not possible to pick a certain slave server for query execution. + + + Full control on server selection can be gained using a callback function. + Use of a callback is recommended to expert users only because the callback + has to cover all cases otherwise handled by the plugin. + + + The plugin will invoke the callback function for selecting a server from the + lists of configured master and slave servers. The callback function + inspects the query to run and picks a server for query execution by returning + the hosts URI, as found in the master and slave list. + + + If the lazy connections are enabled and the callback choses a slave server for + which no connection has been established so far and establishing the connection + to the slave fails, the plugin will return an error upon the next action + on the failed connection, for example, when running a query. It is the + responsibility of the application developer to handle the error. For example, + the application can re-run the query to trigger a new server selection and + callback invocation. If so, the callback must make sure to select + a different slave, or check slave availability, before returning to + the plugin to prevent an endless loop. + + + + + &reftitle.parameters; + + + function + + + The function to be called. Class methods may also be invoked + statically using this function by passing + array($classname, $methodname) to this parameter. + Additionally class methods of an object instance may be called by passing + array($objectinstance, $methodname) to this parameter. + + + + + + + + &reftitle.returnvalues; + + Host to run the query on. The host URI is to be taken from the + master and slave connection lists passed to the callback function. + If callback returns a value neither found in the master nor in the slave + connection lists the plugin will fallback to the second pick method configured + via the pick[] setting in the plugin configuration file. + If not second pick method is given, the plugin falls back to the build-in + default pick method for server selection. + + + + + &reftitle.examples; + + + <function>mysqlnd_ms_set_user_pick_server</function> example + + + + +query("SELECT 1 FROM DUAL"))) + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +else + $res->close(); + +if (!($res = $mysqli->query("SELECT 2 FROM DUAL"))) + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +else + $res->close(); + + +if (!($res = $mysqli->query("SELECT * FROM table_on_slave_a_only"))) + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +else + $res->close(); + +$mysqli->close(); +?> +]]> + + &example.outputs; + + + + + + + + + &reftitle.seealso; + + + + mysqlnd_ms_query_is_select + + + + + + + + diff --git a/reference/mysqlnd_ms/ini.xml b/reference/mysqlnd_ms/ini.xml new file mode 100755 index 0000000000..36b85c32ea --- /dev/null +++ b/reference/mysqlnd_ms/ini.xml @@ -0,0 +1,128 @@ + + + +
+ &reftitle.runtime; + &extension.runtime; + + + Mysqlnd_ms &ConfigureOptions; + + + + &Name; + &Default; + &Changeable; + &Changelog; + + + + + mysqlnd_ms.enable + 0 + its PHP_INI_* value + + + + mysqlnd_ms.force_config_usage + 0 + its PHP_INI_* value + + + + mysqlnd_ms.ini_file + + its PHP_INI_* value + + + + mysqlnd_ms.collect_statistics + + its PHP_INI_* value + + + + +
+
+ + &ini.descriptions.title; + + + + + + mysqlnd_ms.enable + integer + + + + Enables or disables the plugin. If set to disabled, the extension will not plug + into + mysqlnd to proxy internal + mysqlnd C API calls. + + + + + + mysqlnd_ms.force_config_usage + integer + + + + If enabled the plugin checks if the host (server) parameter value of any + MySQL connection attempt matches a section name from the plugin configuration + file. If not, the connection attempt is blocked. + + + + + + mysqlnd_ms.ini_file + string + + + + Plugin specific configuration file. + + + + + + mysqlnd_ms.collect_statistics + integer + + + + Enables or disables the collection of statistics. The collection of + statistics is disabled by default for performance reasons. + Statistics are returned by the function + mysqlnd_ms_get_stats. + + + + + +
+ + diff --git a/reference/mysqlnd_ms/quickstart.xml b/reference/mysqlnd_ms/quickstart.xml new file mode 100755 index 0000000000..1c3a25f7ea --- /dev/null +++ b/reference/mysqlnd_ms/quickstart.xml @@ -0,0 +1,611 @@ + + + + Quickstart and Examples + + The mysqlnd replication load balancing plugin is easy to use. + The quickstart will demo typical use-cases and give practical advice on getting + started. + + + It is strongly recommended to read the reference sections in addition to the + quickstart. The quickstart tries to avoid discussing theoretical concepts + and limitations. Instead, it will link to the reference sections. It is safe + to begin with the quickstart. However, before using the plugin in mission critical + environments we urge you to read additionally the background information from the + reference sections. + +
+ Setup + + The plugin is implemented as a PHP extension. + Please, follow the + installation instructions to + install the + PECL/mysqlnd_ms extension. + Then, load the extension into PHP and activate the plugin in the PHP configuration + file using the PHP configuration directive named + mysqlnd_ms.enable. + + + The plugin is using its own configuration file. Use the PHP + configuration directive + mysqlnd_ms.ini_file + to set the full path to the plugin-specific configuration file. + This file must be readable by PHP. + + + + Enabling the plugin (php.ini) + + + + + + + Create a plugin-specific configuration file. Save the file to the path + set by the PHP configuration directive + mysqlnd_ms.ini_file. + The plugin-specific file must be readable by PHP. + + + The plugins configuration file is divided into one or more sections. + Each section has a name, for example, myapp. Every section + makes its own set of configuration settings. + + + A section must at least list the MySQL replication master server. + The plugin supports using only one master server per section. Multi-master + MySQL replication setups are not supported. + Use the configuration directive + master[] + to set the hostname and the port or socket of the MySQL master server. + + + + Minimal plugin-specific configuration file (mysqlnd_ms_plugin.ini) + + + + + + + It is allowed to set no MySQL slave server but it is not recommended to do. + You should always configure at least one slave server as well. Slave servers + are set using the configuration directive + slave[]. + A configuration section may contain no, one or multiple + slave[] directives to set no, one or multiple + MySQL slaves. + + + + Recommended minimal plugin-specific config (mysqlnd_ms_plugin.ini) + + + + + + + If there are + at least two servers in total, the plugin can start to load balance and switch + connections. Switching connections is not always transparent and can cause + issues in certain cases. The reference section on + connection pooling and switching, + transaction handling, + fail over + load balancing and + read-write splitting gives details. + For now you can continue reading the quickstart. Potential pitfalls + will be described later in the quickstart guide. + + + It is responsibility of the application to handle potential issues caused + by connection switches. By always configuring a master and at lease one slave + server you can be sure to detect issues early because switches become + possible. + + + The MySQL master and MySQL slave servers, which you configure, do not need to + be part of MySQL replication setup. For testing purpose you can use single + MySQL server and make it known to the plugin as a master and slave server + as shown below. This could help you to detect many potential issues with + connection switches. However, such a setup will not be prone to the issues + caused by replication lag. + + + + Using one server as a master and as a slave (testing only!) + + + + + + +
+ +
+ Running statements + + The plugin can be used with any PHP MySQL extension + (mysqli, + mysql, + PDO_MYSQL) + compiled to use the mysqlnd library. + PECL/mysqlnd_ms plugs into the mysqlnd library. + It does not change the PHP MySQL extensions and their API. + + + Whenever a connection to MySQL is being opened, the plugin compares the host + parameter value of the connect call with the section names + from the plugin specific configuration file. If, for example, the + plugin specific configuration file has a section myapp + the section should be referenced by opening a MySQL connection to the + host myapp + + + + Plugin specific configuration file (mysqlnd_ms_plugin.ini) + + + + + + + + Opening a load balanced connection + + +]]> + + + + + All of three connections opened in the example will be load balanced. + The plugin will send read-only statements to the MySQL slave server with the + IP 192.168.2.27 and listening on port 3306 + for MySQL client connection. All other statements will be directed to the + MySQL master server running on the host localhost accepting + MySQL client connection on the Unix domain socket /tmp/mysql.sock. + The plugin will use the user name username and the password + password to connect to any of the MySQL servers listed in + the section myapp of the plugins configuration file. Upon + connect, the plugin will select database as the current + schemata. The username, password and schema name are taken from the connect + API calls and used for all servers. In other words: you must use the same + username and password for every MySQL server listed in a plugin configuration + file section. + + + The plugin does not change the API for running statements. + Read-write splitting + works out of the box. The following example assumes that there is no + significant replication lag between the master and the slave. + + + + Executing statements + +query("DROP TABLE IF EXISTS test")) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} +if (!$mysqli->query("CREATE TABLE test(id INT)")) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} +if (!$mysqli->query("INSERT INTO test(id) VALUES (1)")) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} + +/* read-only: statement will be run on a slave */ +if (!($res = $mysqli->query("SELECT id FROM test")) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} else { + $row = $res->fetch_assoc(); + $res->close(); + printf("Slave returns id = '%s'\n", $row['id']; +} +$mysqli->close(); +?> +]]> + + &example.outputs; + + + + + + + + The plugin does not support native prepared statements. Prepared + statements are not load balanced. Most users of + PDO_MYSQL + will be unaffected by this restriction because + PDO_MYSQL is using a + client-side prepared statement emulation by default. + + +
+ +
+ Connection state + + The plugin changes the semantics of a PHP MySQL connection handle. + A connection handle does no longer represent a single MySQL client-server + network connection but a connection pool. The connection pool consists + of a master connection and none, one or multiple slave connections. + + + Every connection from the connection pool has its own state. For example, + SQL user variables, temporary tables and transactions are part of the state. + Please, find a complete list of what belongs to the state of a connection + at the concepts page on + connection pooling and switching. + If the plugin decides to switch connections for load balancing the + application could be given connection which has a different state. + Applications must be made aware of this! + + + + Plugin config with one slave and one master + + + + + + + + Pitfall: connection state and SQL user variables + +query("SET @myrole='master'")) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} + +/* Connection 2, run on slave because SELECT */ +if (!($res = $mysqli->query("SELECT @myrole AS _role"))) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} else { + $row = $res->fetch_assoc(); + $res->close(); + printf("@myrole = '%s'\n", $row['_role']); +} +$mysqli->close(); +?> +]]> + +&example.outputs; + + + + + + + The example openes a load balanced connection and executes two statements. + The first statement SET @myrole='master' does not begin + with the string SELECT. Therefore the plugin does not + recognize it as a read-only query which shall be run on a slave. The + plugin runs the statement on the connection to the master. The statement + sets a SQL user variable which is bound to the master connection. The + state of the master connection has been changed. + + + The next statement is SELECT @myrole AS _role. + The plugin does recognize it as a read-only query and sends it to + the slave. The statement is run on a connection to the slave. This + second connection does not have any SQL user variables bound to it. + It has a different state than the first connection to the master. + The requested SQL user variable is not set. The example script prints + @myrole = ''. + + + It is the responsibility of the application developer to take care + of the connection state. The plugin does not monitor all + connection state changing activities. Monitoring all possible cases would + be a very CPU intensive task, if it could be done at all. + + + The pitfalls can easily be worked around using SQL hints. + +
+ +
+ SQL Hints + + SQL hints can be used to force the plugin to pick a certain server from + the connection pool. Hinting the plugin to use a certain server can solve + issues caused by connection switches and connection state. + + + SQL hints are standard compliant SQL comments. Because + SQL comments are supposed to be ignored by SQL processing systems they + do not infere with other programs such as the MySQL Server, the MySQL Proxy + or a firewall. + + + Three SQL hints are supported by the plugin: + MYSQLND_MS_MASTER_SWITCH, + MYSQLND_MS_SLAVE_SWITCH and + MYSQLND_MS_LAST_USED_SWITCH. + MYSQLND_MS_MASTER_SWITCH makes the plugin run a statement + on the master, MYSQLND_MS_SLAVE_SWITCH enforces the use + of the slave and MYSQLND_MS_MASTER_SWITCH will run a + statement on the same server that has been used for running the previous + statement. + + + The plugin scans the beginning of a statement for the existance of a SQL + hint. SQL hints are only recognized if they appear at the very beginning of + the statement. + + + + Plugin config with one slave and one master + + + + + + + + SQL hints to prevent connection switches + +query("SET @myrole='master'")) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} + +/* Connection 1, run on master because of SQL hint */ +if (!($res = $mysqli->query(sprintf("/*%s*/SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)))) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} else { + $row = $res->fetch_assoc(); + $res->close(); + printf("@myrole = '%s'\n", $row['_role']); +} +$mysqli->close(); +?> +]]> + +&example.outputs; + + + + + + + In the example the session variables issue from the previous page is solved + using MYSQLND_MS_LAST_USED_SWITCH to prevent switching + from the master to a slave when running the SELECT statement. + + + SQL hints can also be used to run SELECT statements + on the MySQL master server. This may be desired if the MySQL slave servers + tend to be behind the master but you need current data from the database. + + + + Fighting replication lag + +query(sprintf("/*%s*/SELECT critical_data FROM important_table", MYSQLND_MS_MASTER_SWITCH))) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} +?> +]]> + + + + + use case may include the creation of tables on a slave. + If no SQL hint is given, the plugin will send CREATE + and INSERT statements to the master. Use the + SQL hint MYSQLND_MS_SLAVE_SWITCH if you want to + run any such statement on a slave, for example, to build temporary + reporting tables. + + + + Table creation on a slave + +query(sprintf("/*%s*/CREATE TABLE slave_reporting(id INT)", MYSQLND_MS_SLAVE_SWITCH))) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} +/* Continue using this particular slave connection */ +if (!$mysqli->query(sprintf("/*%s*/INSERT INTO slave_reporting(id) VALUES (1), (2), (3)", MYSQLND_MS_LAST_USED_SWITCH))) { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} +/* Don't use MYSQLND_MS_SLAVE_SWITCH which would allow switching to another slave! */ +if ($res = $mysqli->query(sprintf("/*%s*/SELECT COUNT(*) AS _num FROM slave_reporting", MYSQLND_MS_LAST_USED_SWITCH))) { + $row = $res->fetch_assoc(); + $res->close(); + printf("There are %d rows in the table 'slave_reporting'", $row['_num']); +} else { + printf("[%d] %s\n", $mysqli->errno, $mysqli->error); +} +$mysqli->close(); +?> +]]> + + + + + The SQL hint MYSQLND_MS_LAST_USED forbids switching + connection and forces the use of the previously used connection. + +
+ +
+ Transactions + + The current version of the plugin is not transaction safe, + because it is not transaction aware. SQL transactions are + units of work to be run on a single server. + The plugin does not know when the unit of work starts and when it ends. + Therefore, the plugin may decide to switch connections in the middle + of a transaction. + + + You must use SQL hints to work around this limitation. + + + + Plugin config with one slave and one master + + + + + + + + Using SQL hints for transactions + +query("START TRANSACTION")) { + /* Please use better error handling in your code */ + die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); +} + +/* Prevent connection switch! */ +if (!$mysqli->query(sprintf("/*%s*/INSERT INTO test(id) VALUES (1)", MYSQLND_MS_LAST_USED_SWITCH)))) { + /* Please do proper ROLLBACK in your code, don't just die */ + die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); +} +if ($res = $mysqli->query(sprintf("/*%s*/SELECT COUNT(*) AS _num FROM test", MYSQLND_MS_LAST_USED_SWITCH)))) { + $row = $res->fetch_assoc(); + $res->close(); + if ($row['_num'] > 1000) { + if (!$mysqli->query(sprintf("/*%s*/INSERT INTO events(task) VALUES ('cleanup')", MYSQLND_MS_LAST_USED_SWITCH)))) { + die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); + } + } +} else { + die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); +} +if (!$mysqli->query(sprintf("/*%s*/UPDATE log SET last_update = NOW()", MYSQLND_MS_LAST_USED_SWITCH)))) { + die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); +} +if (!$mysqli->query(sprintf("/*%s*/COMMIT", MYSQLND_MS_LAST_USED_SWITCH)))) { + die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); +} + +$mysqli->close(); +?> +]]> + + + + + Future versions of the plugin may be made aware of transactions started, + rolled back and committed using API calls. Therefore, whenever possible + you should start using API calls to control transactions unlike using + SQL statements, as shown in the above example. + +
+
+ diff --git a/reference/mysqlnd_ms/reference.xml b/reference/mysqlnd_ms/reference.xml new file mode 100755 index 0000000000..3b444a72c4 --- /dev/null +++ b/reference/mysqlnd_ms/reference.xml @@ -0,0 +1,30 @@ + + + + + Mysqlnd_ms &Functions; + + &reference.mysqlnd-ms.entities.functions; + + + + diff --git a/reference/mysqlnd_ms/setup.xml b/reference/mysqlnd_ms/setup.xml new file mode 100755 index 0000000000..5e1b3923b4 --- /dev/null +++ b/reference/mysqlnd_ms/setup.xml @@ -0,0 +1,329 @@ + + + + + &reftitle.setup; + +
+ &reftitle.required; + + PHP 5.3.6 or newer. + + + The mysqlnd_ms replication and load balancing + plugin supports all PHP applications and all availablePHP MySQL extensions + (mysqli, + mysql, + PDO_MYSQL). + The PHP MySQL extension must be configured to use + mysqlnd in order to be able + to use the mysqlnd_ms plugin for + mysqlnd. + +
+ + &reference.mysqlnd-ms.configure; + &reference.mysqlnd-ms.ini; + +
+ Plugin configuration file + + The plugin is using its own configuration file. The configuration file + holds information on the MySQL replication master server, + the MySQL replication slave servers, the server pick (load balancing) policy, + the failover strategy and the use of lazy connections. + + + The PHP configuration directive + mysqlnd_ms.ini_file + is used to set the plugins configuration file. + + + The configuration file minics standard php.ini format. + It consists of one or more sections. Every section defines its own unit + of settings. There is no global section for setting defaults. + + + Applications reference sections by their name. Applications use section names + as the host (server) parameter to the various connect methods of the + mysqli, + mysql and + PDO_MYSQL extensions. Upon connect + the mysqlnd plugin compares the hostname + with all section names from the plugin configuration file. If hostname and + section name match, the plugin will load the sections settings. + + + + Using section names example + + + + + +]]> + + + + + Section names are strings. It is valid to use a section name such as + 192.168.2.1, 127.0.0.1 or + localhost. If, for example, an application + connects to localhost and a plugin + configuration section [localhost] exists, the + semantics of the connect operation are changed. The application will + no longer only use the MySQL server running on the host + localhost but the plugin will start to load balance + MySQL queries following the rules from the [localhost] + configuration section. This way you can load balance queries from + an application without changing the applications source code. + + + The master[], slave[] + and pick[] configuration directives use a list-like syntax. + Configuration directives supporting list-like syntax may appear multiple + times in a configuration section. The plugin maintains the order in + which entries appear when interpreting them. For example, + the below example shows two slave[] configuration + directives in the configuration section [myapp]. + If doing round-robin load balancing for read-only queries, the plugin + will send the first read-only query to the MySQL server + mysql_slave_1 because it is the first in the list. + The second read-only query will be send to the MySQL server + mysql_slave_2 because it is the second in the list. + Configuration directives supporting list-like syntax result are ordered + from top to bottom in accordance to their appearance within a configuration + section. + + + + List-like syntax + + + + + + + Here is a short explanation of the configuration directives that can be used. + + + + + + master[] + string + + + + URI of a MySQL replication master server. The URI follows the syntax + hostname[:port|unix_domain_socket]. + + + The plugin supports using only one master server. + + + Setting a master server is mandatory. The plugin will report a + warning upon connect if the user has failed to provide a master + server for a configuration section. + The warning may read + (mysqlnd_ms) Cannot find master section in config. + Furthermore the plugin may set an error code for the connection handle such as + HY000/2000 (CR_UNKNOWN_ERROR). The corresponding error + message depends on your language settings. + + + + + + slave[] + string + + + + URI of one or more MySQL replication slave servers. The URI follows the syntax + hostname[:port|unix_domain_socket]. + + + The plugin supports using one or more slave servers. + + + Setting a slave server is mandatory. The plugin will report a + warning upon connect if the user has failed to provide at least one slave + server for a configuration section. The warning may read + (mysqlnd_ms) Cannot find slaves section in config. + Furthermore the plugin may set an error code for the connection handle such as + HY000/2000 (CR_UNKNOWN_ERROR). The corresponding error + message depends on your language settings. + + + + + + pick[] + string + + + + Load balancing (server picking) policy. Supported policies: + random, random_once (default), + roundrobin, user. + + + If no load balancing policy is set, the plugin will default to + random_once. The random_once + policy picks a random slave server when running the first read-only + statement. The slave server will be used for all read-only + statements until the PHP script execution ends. + + + The random policy will pick a random server whenever + a read-only statement is to be executed. + + + If using + roundrobin the plugin iterates over the list of + configured slave servers to pick a server for statement execution. + If the plugin reaches the end of the list, it wraps around to the beginning + of the list and picks the first configured slave server. + + + Setting more than one load balancing policy for a configuration + section makes only sense in conjunction with user + and mysqlnd_ms_set_user_pick_server. If the + user defined callback fails to pick a server, the plugin falls + back to the second configured load balancing policy. + + + + + + failover + string + + + + Failover policy. Supported policies: + disabled (default), master. + + + If no failover policy is set, the plugin will not do any + automatic failover (failover=disabled). Whenever + the plugin fails to connect a server it will emit a warning and + set the connections error code and message. Thereafter it is up to + the application to handle the error and, for example, resent the + last statement to trigger the selection of another server. + + + If using failover=master the plugin will implicitly + failover to a slave, if available. Please check the + concepts documentation to learn about potential + pitfalls and risks of using failover=master. + + + + + + lazy_connections + bool + + + + Controls the use of lazy connections. Lazy connections + are connections which are not opened before the client sends the first + connection. + + + It is strongly recommended to use lazy connections. + Lazy connections help to keep the the number of open connections low. + If you disable lazy connections and, for example, configure one MySQL + replication master server and two MySQL replication slaves, the + plugin will open three connections upon the first call to a + connect function although the application might use the master + connection only. + + + Lazy connections bare a risk if you make heavy use of actions + which change the state of a connection. The plugin does not dispatch + all state changing actions to all connections from the connection pool. + The few dispatched actions are applied to already opened connections + only. Lazy connections opened in the future are not affected. + If, for example, the connection character set is changed using a + PHP MySQL API call, the plugin will change the character set of all + currently opened connection. It will not remeber the character set + change to apply it on lazy connections opened in the future. As a + result the internal connection pool would hold connections using + different character sets. This is not desired. Remember that character + sets are taken into account for escaping. + + + + + + master_on_write + bool + + + + If set, the plugin will use the master server only after the + first statement has been executed on the master. Applications + can still send statements to the slaves using SQL hints to + overrule the automatic decision. + + + The setting may help with replication lag. If an application runs + an INSERT the plugin will, by default, use the + master to execute all following statements, including + SELECT statements. This helps to avoid problems + with reads from slaves which have not replicated the + INSERT yet. + + + + + +
+ +
+ + diff --git a/reference/mysqlnd_ms/versions.xml b/reference/mysqlnd_ms/versions.xml new file mode 100755 index 0000000000..e4246d2b43 --- /dev/null +++ b/reference/mysqlnd_ms/versions.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + +