質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

トランザクション

トランザクションとは、関連・依存する処理を一連の不可分な処理単位として扱う処理方式を指します。トランザクションとして管理された処理は「すべて成功」か「すべて失敗」のいずれかであることが保証される。処理に失敗した場合は、一連の処理がロールバックされます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

6369閲覧

SQLAlchemyのトランザクションについて

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

トランザクション

トランザクションとは、関連・依存する処理を一連の不可分な処理単位として扱う処理方式を指します。トランザクションとして管理された処理は「すべて成功」か「すべて失敗」のいずれかであることが保証される。処理に失敗した場合は、一連の処理がロールバックされます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/01/08 13:15

前提・実現したいこと

バッチを複数並列に実行することを想定しています。
その場合、DBへの書き込みは、session.commit()すればいいだけなのでしょうか?
マルチスレッドでも問題なく動作し、適切な場所でcommitorrollbackされるのでしょうか?
サンプルコードを作成して試してみて、実現できているように後述する疑問が残ってしましました。

試したこと

下記のようにsetting.pyにsessonを定義し
db関連をまとめたパッケージの__init__.pyimportしています

python

1# setting.py 2from sqlalchemy import create_engine 3from sqlalchemy.ext.declarative import declarative_base 4from sqlalchemy.orm import sessionmaker, scoped_session 5 6# DB設定 7USERNAME = "test" 8PASSWORD = "test" 9HOST = "127.0.0.1" 10DBNAME = "TEST" 11CHARSET = "utf8" 12ENCODING = "utf-8" 13DB_ECHO = True 14 15# mysql 16DATABASE = f"mysql://{USERNAME}:{PASSWORD}@{HOST}/{DBNAME}?charset={CHARSET}" 17 18ENGINE = create_engine( 19 DATABASE, 20 encoding=ENCODING, 21 echo=DB_ECHO 22) 23 24# session作成 25session = scoped_session( 26 sessionmaker( 27 autocommit=False, 28 autoflush=False, 29 bind=ENGINE 30 ) 31) 32 33DbBase = declarative_base()

マルチスレッドで2テーブルにinsertするテストコードを実行してみました

python

1# main 2from db import DbBase, session, ENGINE 3from db.job1 import Job1 4from db.job2 import Job2 5 6import threading 7import time 8 9DbBase.metadata.drop_all(bind=ENGINE, tables=[Job1.__table__, Job2.__table__]) 10DbBase.metadata.create_all(bind=ENGINE, tables=[Job1.__table__, Job2.__table__]) 11 12def create_sample1(): 13 14 for i in range(1,1000): 15 job = Job1() 16 job.name = f"TEST{i}" 17 job.note = i 18 session.add(job) 19 time.sleep(0.01) 20 21 session.rollback() 22 23 24def create_sample2(): 25 26 for i in range(1, 1000): 27 job = Job2() 28 job.name = f"TEST{i}" 29 session.add(job) 30 time.sleep(0.02) 31 32 session.commit() 33 34 35thread1 = threading.Thread(target=create_sample1) 36thread2 = threading.Thread(target=create_sample2) 37 38 39thread1.start() 40thread2.start() 41

試した上での疑問

job1のほうはrollbackされ、job2はcommitされており実現はされているような気はします。
ただ、上記ソースではトランザクションが始まるタイミングがわからず、本当に大丈夫なのか?という不安も解消されていません。

sessionはグローバルで定義されており、共通に利用しています。
それなのに、なぜ片方のみrollbackができるのでしょうか?どこからトランザクションが開始されるのでしょうか?

※ トランザクション開始を明示するならと
session.begin()と書くとautocommit=Falseの時は、トランザクションがすでに貼られていますと言われ
session.begin_nested()と書くと、おそらくmysqlには対応していないのかinsertが反映されてませんでした。

もやもやっとした疑問のため、わかりづらい箇所があるかと思いますが
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

解決しました。

参考:
https://stackoverflow.com/questions/6297404/multi-threaded-use-of-sqlalchemy

理解した内容を要約すると
Sessionオブジェクトはスレッドセーフではない
・マルチスレッドで使いたければ、スレッドローカルストレージを使いなさい
scoped_sessionを使うと、デフォルトでスレッドローカルストレージを使っています
・そのため、スレッド単位で1つのセッションです
・トランザクションは、commitorrollback直後に新しいのが張られます

上記ソースで、トランザクションは問題ないという結論になりました。

投稿2020/01/08 14:54

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問