3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

mysql-connector-python でcommit()が失敗するケース

Last updated at Posted at 2018-09-27

前提

使用バージョン

テーブル構成

  • IDと名前の2つだけのカラム.
  • 既存で1レコードだけデータがある状態とする.
MariaDB [mydb]> desc tbl;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

MariaDB [mydb]> select * from tbl;
+------+------+
| id   | name |
+------+------+
|    1 | shio |
+------+------+

DBへの接続方法

  • 接続情報を辞書型変数で宣言して利用する.
  • 変数connでデータベースへの接続を確立する.
import mysql.connector

# DB接続情報
config = {
    'host': 'myserver',
    'user': 'myusername',
    'password': 'mypassword',
    'database': 'mydb'
}
conn = mysql.connector.connect(**config) # DBへのコネクション確立
print(conn.is_connected()) # -> True

本題

DB書き込みが失敗する場合をケース別に.

ケース1: コネクション切断後にクエリ実行する場合

(当たり前)

print(conn.is_connected()) # -> True
cursor = conn.cursor() # カーソルを定義

# 実行クエリ1
query = '''INSERT INTO tbl(id, name) VALUES(2, 'koro') ; '''
cursor.execute(query) # クエリ実行
conn.commit() # コミット. (2, koro) のデータは問題なく書き込める.
conn.close() # ここでDBへのコネクション切断
print(conn.is_connected()) # -> False

# 実行クエリ2
query = '''INSERT INTO tbl(id, name) VALUES(3, 'haku') ; '''
cursor.execute(query) # -> Traceback: Lost connection to MySQL server at 'my_server:3306', system error: Connection not available.
# conn.commit()

同じようにカーソルを閉じた後にもクエリ実行できない

print(conn.is_connected()) # -> True
cursor = conn.cursor() # カーソルを定義

# 実行クエリ1
query = '''INSERT INTO tbl(id, name) VALUES(2, 'koro') ; '''
cursor.execute(query) # クエリ実行
conn.commit() # コミット. この場合も(2, koro) のデータは問題なく書き込める.
cursor.close() # カーソルのclose
print(conn.is_connected()) # -> True

# 実行クエリ2
query = '''INSERT INTO tbl(id, name) VALUES(3, 'haku') ; '''
cursor.execute(query) # Traceback: Cursor is not connected
#conn.commit()

コネクションやカーソルのclose()は最後に行えば良いだけの話.
疑問なのはcursor.close()の使い所.
conn.close()ではなくあえてじゃなくてcursor.close()を使うメリットがあるケースって??

ケース2: SET句で変数を使う場合

こっちが本題

print(conn.is_connected()) # -> True
cursor = conn.cursor() # カーソルを定義

# 実行クエリ
query = '''
    SET @name = 'lemo';
    INSERT INTO tbl(id, name) VALUES(2, @name) ;
    '''
cursor.execute(query) # クエリ実行
conn.commit() # Traceback: Commands out of sync; you can't run this command now

Commands out of sync; you can't run this command now
(= コマンドは同期されていません。このコマンドは現在実行できません)

なんじゃこりゃ.
普通にGUIツールやコマンドラインで実行したら上手くいくクエリ文なのに.
公式チュートリアルでも特に触れられてない気がする. Issue行き?
select結果を後の代入に使いたい場合, python側の変数に持たせないといけなくてなんだかな〜と.

おわり

ケース別と言いつつ大してネタは無いという.
他のケースや指摘あればコメントください.

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?