カテゴリー
SugiBlog Webエンジニアのためのお役立ちTips

MySQLトランザクションでROLLBACKが効かないケース

MySQLのトランザクションは、処理の途中で失敗した場合に ROLLBACK(ロールバック)で元の状態に戻せる便利な仕組みです。
しかし「必ず元に戻せる」と思っていると落とし穴にはまります。

実は、MySQLには ROLLBACKが効かない(厳密には「元に戻せない」)SQL文 が存在します。

ROLLBACKできるSQL(DML)

一般的なデータ操作言語(DML)はトランザクションで管理でき、ROLLBACKも可能です。

  • INSERT
  • UPDATE
  • DELETE

これらは通常通り、トランザクションの途中で ROLLBACK すれば元の状態に戻せます。

ROLLBACKできないSQL(DDL)

一方、スキーマを変更するようなデータ定義言語(DDL)は注意が必要です。

  • CREATE
  • DROP
  • ALTER
  • TRUNCATE

これらのDDL文を実行すると、MySQLでは 暗黙的に COMMIT が発生 します。そのため、実行後に ROLLBACK しても元に戻すことはできません。
つまり「ROLLBACKがエラーになる」のではなく、「DDLが実行された時点でトランザクションが確定してしまう」イメージです。

他のデータベースとの違い

これはMySQL固有の挙動です。
データベースによってはDDLもトランザクション管理下に置ける場合があります(例:PostgreSQLでは多くのDDLがトランザクション内でROLLBACK可能)。

MySQLを使う際には「DDLは必ず即時確定する」と覚えておくのが安全です。

まとめ

  • INSERT / UPDATE / DELETE はトランザクションで管理でき、ROLLBACK可能
  • CREATE / DROP / ALTER / TRUNCATE は実行時に自動コミットされ、ROLLBACK不可
  • ROLLBACK自体がエラーになるわけではなく、「巻き戻せない」だけ
  • PostgreSQLなど他のDBではDDLもROLLBACK可能な場合がある

参考: MySQL公式ドキュメント – ステートメントをロールバックできない場合

1,179 views

MySQL 既存テーブルの文字コードをutf8mb4に変換する

MySQLのテーブルで文字コードutf8とutf8mb4が混在するシステムをutf8mb4に統一する機会がありました。
そんな時に文字コードや照合順序を確認する方法、変換する方法です。

MySQL:5.7

データベースの文字コードと照合順序を確認する

SELECT
    SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE
    SCHEMA_NAME = 'データベース名';

テーブルの文字コードと照合順序を確認する

SELECT
    TABLE_NAME, TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE
    TABLE_SCHEMA = 'データベース名';

カラムの文字コードと照合順序を確認する

SELECT
    COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
    TABLE_NAME = 'テーブル名';

続きを読む…»

6,796 views

MySQL 外部キー制約を一時的に無効にする

MySQLで外部キー制約を設定しているテーブルは削除等、一部の命令を実行することができません。
開発をしている中でどうしても外部キー制約が邪魔になってしまう場合があります。
その場合は外部キー制約を一時的に無効にすることができます。

外部キー制約を一時的に無効にする

SET foreign_key_checks = 0;

処理が終わったら必ず元に戻しましょう。

SET foreign_key_checks = 1;
1,476 views

Docker + Laravel9 開発環境構築

Dockerを使ってLaravel9の開発環境を構築してみたいと思います。
XAMPPやレンタルサーバーを使うよりお手軽に出来るので是非試してみてください。

OS等の環境は以下の通りです。

OS: Windows10
Docker Desktop: v4.14.1
Visual Studio Code: v1.74.0

Dockerで環境構築

予め必要なファイル等を準備します。
Laravelのプロジェクト名は「laravel-app」と仮定します。

docker/app/000-default.conf
<VirtualHost *:80>
       ServerAdmin webmaster@localhost
       DocumentRoot /var/www/html/laravel-app/public
       ErrorLog ${APACHE_LOG_DIR}/error.log
       CustomLog ${APACHE_LOG_DIR}/access.log combined
       <Directory /var/www/html/laravel-app/public>
           AllowOverride All
       </Directory>
</VirtualHost>
docker/app/Dockerfile
# dockerイメージの選択
# 予めPHPとApacheがインストールされているイメージをDocker Hubからダウンロード
FROM php:8.0-apache

# 設定ファイルをdockerコンテナ内のPHP、Apacheに読み込ませる
# ADD:ローカルのファイルをDockerコンテナ内にコピーする
ADD php.ini /usr/local/etc/php/
ADD 000-default.conf /etc/apache2/sites-enabled/

# Composerのインストール
# RUN:コンテナ内でコマンド実行する
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer

# Node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get install -y nodejs

# ミドルウェアのインストール
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim \
libpng-dev \
libpq-dev \
&& docker-php-ext-install pdo_mysql

# Laravelで必要になるmodRewriteを有効化する
RUN mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
RUN /bin/sh -c a2enmod rewrite

続きを読む…»

3,750 views

指定した文字列が最初に出現する位置を調べるLOCATE関数

LOCATE関数を使うと指定した文字列が最初に出現する位置を調べることができます。

【書式】
LOCATE(substr, str)
LOCATE(substr, str, pos)

【引数】
substr:検索文字列
str:検索対象文字列
pos:オフセット

posは何文字目以降を検索するかを数値で指定します。

例)

mysql> SELECT LOCATE('bar', 'foobarbar');
        -> 4
mysql> SELECT LOCATE('xbar', 'foobar');
        -> 0
mysql> SELECT LOCATE('bar', 'foobarbar', 5);
        -> 7

INSTR関数も同様の動作をしますが、引数の順序が逆なのと、第3引数がないのでご注意ください。

mysql> SELECT INSTR('foobarbar', 'bar');
        -> 4
mysql> SELECT INSTR('xbar', 'foobar');
        -> 0
3,769 views