目次
1.はじめに
2.環境
3.今回実現したかった事・本記事の内容
4.下準備
5.検証用のフローについて
6.検証
7解決方法?
8.解決方法その2
9.まとめ
10.参考資料
1.はじめに
ASTERIA Warp はGUI で使えるのでとても扱いやすいツールだと思います。
一方で、裏で実際にどのようなプログラミングの動きをしているのか分からない・・・、
というデメリットを感じる事が時々あります。
今回はそういった特殊な事態に遭遇してしまい、解決に時間がかかってしまった・・・。という事例をご紹介致します。
2.環境
・ASTERIA Warp 1906.0700
・Aurora 2.10.2(MySQL 5.7.12-log)
・Linux AMI release 2018.03
3.今回実現したかった事・本記事の内容
特定のテーブルのFLG が更新されているかを定期的に確認するバッチを作っていたのですが、うまくいかず・・・。
調査の結果、フローのループ処理中に(意図せず)トランザクションが張られ続けた状態になってしまっている。という事に気づきました。
今回はその事象の共有と解決策をまとめていきます!
4.下準備
Aurora 側に下記のデータが入ったテーブルを用意しました。
mysql> SELECT * FROM ForTest.nakasone_test;
+----+-------+-----+
| id | name | flg |
+----+-------+-----+
| 1 | name1 | 0 |
| 2 | name2 | 0 |
| 3 | name3 | 0 |
+----+-------+-----+
3 rows in set (0.01 sec)
5.検証用のフローについて
今回「トランザクション設定無し」という名前の、このようなフローを作成しました。
コンポーネントの設定値はそれぞれ以下の様にしました。
トランザクション関係の設定は全て「いいえ」にしています。
Mapper1の中身はこのようになっています。何ループ目か分かるようにフロー変数のroop を+1しています。
RDBGet1のSQL はこのようになっています。
SELECT ?roop? AS 'roop回数',
NOW(),
id,
name,
flg
FROM ForTest.nakasone_test
6.検証
先ほどの「トランザクション設定無し」をデバッグ実行していきます。
ステップインで実行していき、RDBGet1のストリームを見てみます。
少し見づらいですが、左から
「ループ回数」、「現在の時間」そして事前準備用意したテーブルの「id」、「name」、「flg」の5つの値になっています。
この状態で別セッションからAurora 側のid = 1のflg を更新してみます。
mysql> UPDATE ForTest.nakasone_test SET flg = 1 WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT NOW(), id, name, flg FROM ForTest.nakasone_test;
+---------------------+----+-------+-----+
| NOW() | id | name | flg |
+---------------------+----+-------+-----+
| 2023-01-06 16:53:49 | 1 | name1 | 1 |
| 2023-01-06 16:53:49 | 2 | name2 | 0 |
| 2023-01-06 16:53:49 | 3 | name3 | 0 |
+---------------------+----+-------+-----+
3 rows in set (0.00 sec)
無事id = 1のflg が1に更新されました。
ということで、Asteria 側でステップインして、2ループ目のRDBGet1のデータを見てみます。
値が変わってませんね・・・。
Aurora の方のinformation_schema.INNODB_TRX テーブルを見てみると、1ループ目のRDBGet1が実行された段階でトランザクションが発行されたままになっていました。
trx_started のタイムゾーンはおそらくUTC なので、+9時間して16:52:13で1ループ目の「現在の時間」と一致してますね。
mysql> SELECT NOW(), trx_id, trx_state, trx_started, trx_query, trx_isolation_level FROM information_schema.INNODB_TRX;
+---------------------+-----------------+-----------+---------------------+-----------+---------------------+
| NOW() | trx_id | trx_state | trx_started | trx_query | trx_isolation_level |
+---------------------+-----------------+-----------+---------------------+-----------+---------------------+
| 2023-01-06 16:55:19 | 329309965267296 | RUNNING | 2023-01-06 07:52:13 | NULL | REPEATABLE READ |
+---------------------+-----------------+-----------+---------------------+-----------+---------------------+
1 row in set (0.00 sec)
mysql> show global variables like '%time_zone%';
+------------------+------------+
| Variable_name | Value |
+------------------+------------+
| system_time_zone | UTC |
| time_zone | Asia/Tokyo |
+------------------+------------+
2 rows in set (0.01 sec)
トランザクション分離レベルが「REPEATABLE READ」なので、ファジーリードが発生しない。(トランザクション中は別のセッションで値を変更しても変更前の値を参照する。)という状況になっているという事だと思います。
7.解決方法?
理由はともかく、トランザクションが発行されたままになってしまうのであれば、ループの終わりにコミットを入れたらいいじゃないか。
という事で、「トランザクション設定無し_ループ後にコミット」という名前の、このようなフローを作成しました。
ループの終わりにEnd2を追加してコミットしてから次のループに行くようにしました。
テーブルの中身は初期値に戻して実行してみます。
これでうまくいくことでしょu
8.解決方法その2
ダメもとで「トランザクション設定無し_ループ後にコミット2」という名前の、このようなフローを作成しました。
SQLCall1を追加して、SQL でコミットするようにしてみました。
先ほどのEnd コンポーネントのコミットでうまくいかなかったので心配ですが試しに実行してみます。
1ループ目です。
別セッションからAurora 側のid = 1のflg を更新します。
mysql> UPDATE ForTest.nakasone_test SET flg = 1 WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT NOW(), id, name, flg FROM ForTest.nakasone_test;
+---------------------+----+-------+-----+
| NOW() | id | name | flg |
+---------------------+----+-------+-----+
| 2023-01-06 17:26:15 | 1 | name1 | 1 |
| 2023-01-06 17:26:15 | 2 | name2 | 0 |
| 2023-01-06 17:26:15 | 3 | name3 | 0 |
+---------------------+----+-------+-----+
3 rows in set (0.00 sec)
SQLCall コンポーネントからのコミット処理が実行されました。
お!2ループ目にRDBGet コンポーネントで更新されたflg データが取れました!
という事でEND コンポーネントのコミットではダメでしたが、DB に直接コミットのクエリを発行する事でトランザクションを抜ける事が出来たようです。
ただし、公式からSQLCall コンポーネントでコミットや、ロールバックを行うと動作保証外となる可能性があるようですので、ご留意下さい。
SQLCallコンポーネントでcommitやrollbackは使えますか?
9.まとめ
トランザクションがが発行され続けた原因は分かりませんでしたが、
DB に明示的にコミットのクエリを流す事で、トランザクションを抜ける事ができるようです。
心残りなのは、トランザクションの設定をしていないはずがトランザクションが張られ続けている。
End コンポーネントでコミットをしてもトランザクションが終了しない。
という謎は残りますが、ここも今後紐解けたらいいなーと思ってます。
私の設定の見落としもあるかもしれないので、情報お持ちの方いらっしゃいましたら共有頂けますと幸いです!
今回は以上となります。長くなってしまいましたが、ここまでご閲覧頂きありがとうございました!
10.参考資料
・Asteria warp adn(SQLCallコンポーネントでcommitやrollbackは使えますか?)(最終閲覧日:2023年1月13日)
https://support.asteria.com/hc/ja/articles/228986647
・FAT47の底辺インフラ議事録(MySQLでトランザクションの4つの分離レベルを試す)(最終閲覧日:2023年1月13日)
https://kikai.hatenablog.jp/entry/20140212/1392171784
・MySQL 5.6 リファレンスマニュアル(21.29.4 INFORMATION_SCHEMA INNODB_TRX テーブル)(最終閲覧日:2023年1月13日)
https://dev.mysql.com/doc/refman/5.6/ja/information-schema-innodb-trx-table.html
・zoo200's MemoMemo(Amazon AuroraのタイムゾーンをUTCからJSTへ変更する)(最終閲覧日:2023年1月13日)
https://zoo200.net/aws-aurora-timezone-utc-to-jst/