以前に以下の記事でBigQueryでsleepをする方法を説明しましたが、これをMultiStatement Transactionと併用する時には注意が必要です。
まず、以下のSQLは5秒で終了します。
BEGIN
DECLARE now TIMESTAMP DEFAULT CURRENT_TIMESTAMP();
DECLARE finish TIMESTAMP DEFAULT TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 5 SECOND);
WHILE now < finish DO
SET now = CURRENT_TIMESTAMP();
END WHILE;
END
一方で、上記のSQLとほぼ同じである以下のSQLは無限ループしてしまいます。
BEGIN
DECLARE now TIMESTAMP DEFAULT CURRENT_TIMESTAMP();
DECLARE finish TIMESTAMP DEFAULT TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 5 SECOND);
BEGIN TRANSACTION; -- この行を追加しただけ
WHILE now < finish DO
SET now = CURRENT_TIMESTAMP();
END WHILE;
END
これら2つのSQLの間にどのような差があるのでしょうか?
下のSQLには、 BEGIN TRANSACTION
があることから、MultiStatement Transaction機能を利用していることが分かります。
そして、この機能がONになると、CURRENT_TIMESTAMPは現在時刻ではなく、トランザクションを開始した時刻を返すようになります。
そのため、 now < finish
という式の両辺は常に同じ値になり、式の評価結果は常にFALSEになり、無限にWHILEから抜け出すことができなくなってしまいます。