Skip to content

Instantly share code, notes, and snippets.

@suin
Created February 16, 2012 05:57
Show Gist options
  • Save suin/1842474 to your computer and use it in GitHub Desktop.
Save suin/1842474 to your computer and use it in GitHub Desktop.
MySQLの「暗黙のトランザクションコミット」対策:トランザクション中でも安全にCREATE TABLEなどをする方法 ref: http://qiita.com/items/2545
<?php
$dbname = 'test';
$host = 'localhost';
$user = 'root';
$pass = 'root';
$dsn = sprintf('mysql:dbname=%s;host=%s', $dbname, $host);
$options = array(
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_AUTOCOMMIT => true,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
PDO::ATTR_EMULATE_PREPARES => false,
);
/**
* クエリーをログできるようにしたPDO
*/
class MyPDO extends PDO
{
public function query($query)
{
$this->_print($query);
$arguments = func_get_args();
return call_user_func_array(array('parent', 'query'), $arguments);
}
public function beginTransaction()
{
$this->_print('BEGIN');
parent::beginTransaction();
}
public function rollBack()
{
$this->_print('ROLLBACK');
parent::rollBack();
}
protected function _print($query)
{
static $count = 1;
echo $count.') '.$query.';'.PHP_EOL;
$count += 1;
}
}
echo "暗黙のトランザクションコミットが走るかどうかの実験\n\n";
// 下準備
/** @var PDO $pdo */
$pdo = new MyPDO($dsn, $user, $pass, $options);
$pdo->query('DROP TABLE IF EXISTS foo');
$pdo->query('DROP TABLE IF EXISTS baz');
$pdo->query('CREATE TABLE foo (bar VARCHAR(255)) ENGINE=InnoDB');
$pdo->query('INSERT INTO foo (bar) VALUES ("a"), ("b"), ("c")');
// 更新処理
$pdo->beginTransaction(); // トランザクション開始
$pdo->query('DELETE FROM foo'); // fooテーブルのレコードすべて削除
$pdo->query('CREATE TABLE baz (bazbaz VARCHAR(255)) ENGINE=InnoDB'); // 暗黙のトランザクションコミットが走る
$pdo->rollBack(); // ロールバック!
var_export($pdo->query('SELECT * FROM foo')->fetchAll()); // ロールバックが効いていないので fooテーブルには何も残ってない
echo "\n\nCREATE TABLE文を別コネクションにしたら,
暗黙のトランザクションコミットがどうなるかの実験\n\n";
// 下準備
/** @var PDO $pdo */
$pdo = new MyPDO($dsn, $user, $pass, $options);
$pdoAnother = new MyPDO($dsn, $user, $pass, $options);
$pdo->query('DROP TABLE IF EXISTS foo');
$pdo->query('DROP TABLE IF EXISTS baz');
$pdo->query('CREATE TABLE foo (bar VARCHAR(255)) ENGINE=InnoDB');
$pdo->query('INSERT INTO foo (bar) VALUES ("a"), ("b"), ("c")');
// 更新処理
$pdo->beginTransaction(); // トランザクション開始
$pdo->query('DELETE FROM foo'); // fooテーブルのレコードすべて削除
$pdoAnother->query('CREATE TABLE baz (bazbaz VARCHAR(255)) ENGINE=InnoDB'); // 別コネクションなのでトランザクションには影響ない
$pdo->rollBack(); // ロールバック!
var_export($pdo->query('SELECT * FROM foo')->fetchAll()); // ロールバックが効いているので、fooテーブルは元通りになっている
php TransactionWithCreateTable.php
暗黙のトランザクションコミットが走るかどうかの実験
1) DROP TABLE IF EXISTS foo;
2) DROP TABLE IF EXISTS baz;
3) CREATE TABLE foo (bar VARCHAR(255)) ENGINE=InnoDB;
4) INSERT INTO foo (bar) VALUES ("a"), ("b"), ("c");
5) BEGIN;
6) DELETE FROM foo;
7) CREATE TABLE baz (bazbaz VARCHAR(255)) ENGINE=InnoDB;
8) ROLLBACK;
9) SELECT * FROM foo;
array (
)
CREATE TABLE文を別コネクションにしたら,
暗黙のトランザクションコミットがどうなるかの実験
10) DROP TABLE IF EXISTS foo;
11) DROP TABLE IF EXISTS baz;
12) CREATE TABLE foo (bar VARCHAR(255)) ENGINE=InnoDB;
13) INSERT INTO foo (bar) VALUES ("a"), ("b"), ("c");
14) BEGIN;
15) DELETE FROM foo;
16) CREATE TABLE baz (bazbaz VARCHAR(255)) ENGINE=InnoDB;
17) ROLLBACK;
18) SELECT * FROM foo;
array (
0 =>
array (
'bar' => 'a',
),
1 =>
array (
'bar' => 'b',
),
2 =>
array (
'bar' => 'c',
),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment