バッチ処理とトランザクション処理

こんにちは、Yuinaです😺

今日は、MYSQLとPythonを活用してバッチ処理に挑戦してみます。

使用する環境は以下の通りです。

  • OS:Mac
  • 言語:Python 3.12
  • データベース:MYSQL(Ubuntu)

どうぞよろしくお願いします!

バッチ処理とトランザクション

バッチ処理とは、大量のデータを定期的に更新する場合に、コンピュータが用いる処理のことです。

データベースを使ったバッチ処理の中にはトランザクションがあります。

トランザクションとは、2つの更新の処理を同時に行うときに、ひとまとめに扱う処理のことです。

販売する化粧品を管理するデータベースを例にして説明していきます。

こちらのテーブルには、商品名(product_name)と値段(price)が入っています。

テーブルに以下の3つのproduct_nameとpriceのデータを新たに追加したいです。

queries = [
    ("アイシャドウ(ブルー)", 1000),
    ("ファンデーション(オークル)", 1200),
    ("ルージュ(ピンク)", "abc")
]

3つ目のpriceのデータが文字列になっているので、追加の処理が失敗しそうです。

このときトランザクションの処理では、3つ目のデータだけではなく、

1つ目と2つ目のデータも保存せずに終了することができます。

この処理をロールバックと言います。

では、データの追加が成功する場合はどうなるでしょうか。

以下では、3つ目のpriceのデータを文字列から数値に修正しました。

queries = [
    ("アイシャドウ(ブルー)", 1000),
    ("ファンデーション(オークル)", 1200),
    ("ルージュ(ピンク)", 1500)
]

この場合は、3つのデータの全てが正常に追加されます。

トランザクションのルール:

  • COMMIT トランザクション含まれる処理で変更があれば上書き保存して、トランザクションを終了する
  • ROLLBACK トランザクションに含まれていた処理を、保存せずに終了する

Python 実践データ分析 100本ノック 第2版 [ 下山輝昌 ]

価格:2640円
(2025/5/5 22:12時点)
感想(1件)

実際にやってみよう

1.ータベース作成

テーブル作成:

CREATE TABLE cosmetics (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(255),
    price INT UNSIGNED
);

データをインポート:

LOAD DATA INFILE '/path/to/cosmetics_after_update.csv'
INTO TABLE cosmetics
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(product_id, product_name, price);

中身を確認します。

バックアップをとる:

誤った更新をしてしまったときのために、念のためバックアップを取ります。

下記のコードでテーブルのデータが新しいテーブルに まるっとコピーされます!

CREATE TABLE cosmetics_backup AS
SELECT * FROM cosmetics;

中身を確認します。

2.プログラム作成

DBにデータを追加するプログラムを作成します。

プログラム全体はこんな感じです。

import mysql.connector

conn = mysql.connector.connect(

      host='***',
      user='***',
      password='***',
      database='***',
      connection_timeout=5
      )

cursor = conn.cursor()

queries = [
    (21,"コスメデコルテアイシャドウ(青)", 1000),
    (22,"リップモンスター(ワイン色)", 1200),
    (23,"リップモンスター(薄桃色)", 1500)
]


try:
    for product_id,product_name, price in queries:
        cursor.execute(
            "INSERT INTO cosmetics (product_id,product_name, price) VALUES (%s, %s,%s)",
            (product_id,product_name, price)
        )
    
    conn.commit()  # 全部成功したら保存!

except mysql.connector.Error as err:
    print("エラーが発生しました:", err)
    conn.rollback()  # どれか失敗したら全部なかったことに!

finally:
    conn.close()

3.プログラム実行

まずは成功バージョンから実行していきます。

queries = [
    ("アイシャドウ(ブルー)", 1000),
    ("ファンデーション(オークル)", 1200),
    ("ルージュ(ピンク)", 1500)
]

実行結果です。

データが追加されています。

queries = [
    ("アイシャドウ(ブルー)", 1000),
    ("ファンデーション(オークル)", 1200),
    ("ルージュ(ピンク)", "abc")
]

続いて失敗バージョンです。

コードはこちらです。

import mysql.connector

conn = mysql.connector.connect(

      host='***',
      user='***',
      password='***',
      database='***',
      connection_timeout=5
      )

cursor = conn.cursor()

queries = [
    (24,"コスメデコルテアイシャドウ(青)", 1000),
    (25,"リップモンスター(ワイン色)", 1200),
    (26,"リップモンスター(薄桃色)", "abc")
]


try:
    for product_id,product_name, price in queries:
        cursor.execute(
            "INSERT INTO cosmetics (product_id,product_name, price) VALUES (%s, %s,%s)",
            (product_id,product_name, price)
        )
    
    conn.commit()  # 全部成功したら保存!

except mysql.connector.Error as err:
    print("エラーが発生しました:", err)
    conn.rollback()  # どれか失敗したら全部なかったことに!

finally:
    conn.close()

ターミナルには「エラーが発生しました: 1366 (HY000): Incorrect integer value: ‘abc’ for column ‘price’ at row 1 ***@*** Python 3.13 %」と出てました。

型が異なるのでデータの追加ができないということです。

実行結果を見てみましょう。

データが更新されず、1回目(成功バージョン)のままになりました。

まとめ

今回はバッチ処理の中でもトランザクションについてまとめてみました。

トランザクション処理は、データの一貫性が求められるシナリオでのデータ操作に欠かせない方法なので、内容をよく押さえておきたいと思います。

ありがとうございました!

コメント

タイトルとURLをコピーしました