前提・実現したいこと
バッチを複数並列に実行することを想定しています。
その場合、DBへの書き込みは、session.commit()
すればいいだけなのでしょうか?
マルチスレッドでも問題なく動作し、適切な場所でcommit
orrollback
されるのでしょうか?
サンプルコードを作成して試してみて、実現できているように後述する疑問が残ってしましました。
試したこと
下記のようにsetting.py
にsessonを定義し
db関連をまとめたパッケージの__init__.py
でimport
しています
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が反映されてませんでした。
もやもやっとした疑問のため、わかりづらい箇所があるかと思いますが
よろしくお願いします。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。