|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2013-01-16 09:05 UTC] ilari at exove dot com
Description: ------------ trx_stickiness doesn't seem to detect SAVEPOINT statement as a start of a new transaction thus trx_stickiness doesn't have an affect. Drupal 7 uses SAVEPOINT to implement nested transactions. mysqlnd_ms version in use: 1.4.2 PHP version 5.4.10 MySQL 5.5.29 with InnoDB PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Dec 17 22:00:01 2025 UTC |
Hi, this is not a bug in PECL/mysqlnd_ms. This is something between wrong usage and inconsistent PDO_MySQL implementation. As explained in the PECL/mysqlnd_ms documentation, the plugin will not parse SQL at runtime to detect transaction boundaries. It makes no attempt to detect statements such as COMMIT, START TRANSACTION, SAVEPOINT or ROLLBACK. Instead, it monitors MySQL Client Server C library calls (in mysqlnd) to detect transaction boundaries. Drupal 7.19 begins a transaction using PDO::beginTransaction. PDO::beginTransaction goes down to ext/pdo_mysql/mysql_driver.c:mysql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) and there you find exactly what is NOT supported by MS: /* {{{ mysql_handle_begin */ static int mysql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) { PDO_DBG_ENTER("mysql_handle_quoter"); PDO_DBG_INF_FMT("dbh=%p", dbh); PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("START TRANSACTION") TSRMLS_CC)); } As you can see, PDO_MySQL is using START TRANSACTION to begin is transaction. Because MS does not monitor SQL, it will not be made aware of the start of a transaction. Thus, load balancing will continue. Depending on the MS configuration read write splitting will also continue - to make a long story short: chaos... Unfortunately the MySQL Client Server protocol does not properly announce transaction boundaries, so MS cannot use it. MS will not try to detect trx boundaries inspecting SQL - I would expect it to be error prone. In sum: MS is forced to monitor C API calls or needs to be hinted by the user. Again, PDO_MySQL does not use a C API call to start a transaction and MS is fooled. Workaround: use mysqli or wait for new PHP version with improved PDO_MySQL. SAVEPOINT has nothing to do with the actual issue. START TRANSACTION comes first and marks the point from which on load balancing must not happen any more. On an aside, the way Drupal uses SAVEPOINT could be improved. It would be better if Drupal used some explicit error handling upon setting a SAVEPOINT: nixnutz@linux-fuxh:~/www/drupal-7.19/includes/database> grep -n -R -C10 "'SAVEPOINT" database.inc 1065- public function pushTransaction($name) { 1066- if (!$this->supportsTransactions()) { 1067- return; 1068- } 1069- if (isset($this->transactionLayers[$name])) { 1070- throw new DatabaseTransactionNameNonUniqueException($name . " is already in use."); 1071- } 1072- // If we're already in a transaction then we want to create a savepoint 1073- // rather than try to create another transaction. 1074- if ($this->inTransaction()) { 1075: $this->query('SAVEPOINT ' . $name); 1076- } 1077- else { 1078- parent::beginTransaction(); 1079- } 1080- $this->transactionLayers[$name] = $name; 1081- } 1082- 1083- /** 1084- * Decreases the depth of transaction nesting. 1085- * If the save guard in line 1069 would not exist or ever turns out to be buggy and autocommit mode is used it may happen that an attempt to set a SAVEPOINT is made but the SAVEPOINT is not actually set. Together with the SQL mode used by Drupal nothing but a warning would be returned from MySQL. The failure of setting the SAVEPOINT would most likely not be noted by Drupal. Whatever, this is unrelated to MS and PDO. Ulf