PDO's automatic submission function is enabled on MySQL with autocommit turned off
P粉011912640
P粉011912640 2023-08-08 15:23:46
0
1
510
<p>I was just assigned to a legacy PHP codebase that only used PDO. </p><p>The connection is done using the following pattern: </p><p><br /></p> <pre class="lang-php prettyprint-override"><code>// Connect to MySQL database $con = new mysqli($host, $user, $password, $database); // Check connection if ($con->connect_error) { die("Connection failed: " . $con->connect_error); } $con->autocommit(true); </code></pre> <p>And using that autocommit(true) works as expected even if the MySQL server is configured with SET autocommit = 0. </p><p>Now I'm trying to migrate from normal SQL to prepared statements, so I wrote this</p><p><br /></p> <pre class="lang-php prettyprint-override"><code>$dsn = "mysql:host=$host;dbname=$database"; $pdo = new PDO($dsn, $user, $password); $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, true); $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); </code></pre> <p>and the example function below</p> <pre class="lang-php prettyprint-override"><code>function updateTeam($pdo, $name, $id) { try { $data = [ 'name' => $name, 'id' => $id ]; $sql = "UPDATE teams SET name = :name WHERE id=:id"; $stmt = $pdo->prepare($sql); $stmt->execute($data); // $pdo->commit(); } catch (PDOException $e) { db::$pdo->rollback(); error_log('Failed: ' . $e->getMessage() ); } catch (Exception $exc) { db::$pdo->rollback(); error_log('Failed: ' . $exc->getMessage()); } } </code></pre> <p>Do not submit. I have to uncomment $pdo->commit(); to make it work, which I don't want because it forces me to change every query statement in the application. </p><p>What did I miss in PDO configuration? I tried var_dump($pdo->query('SELECT @@autocommit')->fetchAll()); and the result was </p><p><code></code>< /p> <pre class="brush:php;toolbar:false;">array(1) { [0]=> array(2) { ["@@autocommit"]=> string(1) "0" [0]=> string(1) "0" } }</pre> <p><br /></p>
P粉011912640
P粉011912640

reply all(1)
P粉799885311

PDO's automatic submission is different from MySQL's automatic submission. This means that if you set the value of autocommit to default to 0 in your MySQL configuration, it will not change the default value of PDO::ATTR_AUTOCOMMIT. The default value of PDO::ATTR_AUTOCOMMIT is always true.

Changing the value of PDO::ATTR_AUTOCOMMIT to the same value or any other value that is not a boolean or integer will be ignored. This means that both operations are no-ops:

$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, true); // 因为默认值是true
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); // 转换为布尔值true,与默认值相同

You can trick it by disabling and enabling PDO::ATTR_AUTOCOMMIT:

$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, true);

This will make two calls to the MySQL server and should set MySQL's autocommit value to 1

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template