q4m の動きをまとめてみた。

キューにデータを挿入する際には特に不思議な動作は無いし、普通の insert 文を使うだけなので、割愛。問題は取得時。これも直感にそぐう動作をしていると思う。


queue_wait() にて、owner モードに入ると同時にキューのデータを一件取得する。
取得した時点で、他のコネクションにて queue_wait() を発行しても、同じデータは取得されなくなる。
queue_end() にて、取得したデータをキューから削除する。
queue_wait() を連続して発行すると、2回目からは暗黙的に queue_end() + queue_wait() の動きをする。
queue_abort() を行うことで、取得したデータはキューに返される。
他のコネクションにて、queue_wait() を行うと、そのデータが取得される。


検証してみよう。事前準備として、情報をキューに insert 文を利用してたっぷりと登録しておく。

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|     9887 | 
+----------+
1 row in set (0.00 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.00 sec)

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|        1 | 
+----------+
1 row in set (0.00 sec)

mysql> select * from q4m_t2;
+-----+
| v   |
+-----+
| 106 | 
+-----+
1 row in set (0.00 sec)

mysql> select queue_end();
+-------------+
| queue_end() |
+-------------+
|           1 | 
+-------------+
1 row in set (0.17 sec)

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|     9886 | 
+----------+
1 row in set (0.00 sec)

概略すると以下のようになる。
9887 件

queue_wait() # owner モードに移行。

queue_end() # owner モードを終了

9886 件 # 一件処理された。



では、これが、queue_wait() を連続発行した場合だとどうなるか。

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|     9886 | 
+----------+
1 row in set (0.00 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.00 sec)

mysql> select * from q4m_t2;
+-----+
| v   |
+-----+
| 107 | 
+-----+
1 row in set (0.00 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.07 sec)

mysql> select * from q4m_t2;
+-----+
| v   |
+-----+
| 108 | 
+-----+
1 row in set (0.00 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.04 sec)

mysql> select * from q4m_t2;
+-----+
| v   |
+-----+
| 109 | 
+-----+
1 row in set (0.00 sec)

mysql> select queue_end();
+-------------+
| queue_end() |
+-------------+
|           1 | 
+-------------+
1 row in set (0.04 sec)

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|     9883 | 
+----------+
1 row in set (0.00 sec)


概略すると以下のようになる。
9886 件

queue_wait() # owner モードに移行。

queue_wait() # 既に owner モード。(1)

queue_wait() # 上に同じ。(2)

queue_end() # owner モードを終了(3)

9883 件 # 3件処理された。

要するに、queue_wait() 毎にデータが fetch されている。select * from q4m_t2; することで、 fetch したデータを取得できる。(1) では、107, (2) では 108、(3) では 109 が返却されていることがわかる。


ここで、大事なことは、queue_wait() を 2 回続けて実行すると、2回目の queue_wait() では暗黙的に queue_end() が発行されるということ(内部でどうなってるかは知らない。あくまで表面の動きとしてである)よって・・・

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|     9883 | 
+----------+
1 row in set (0.00 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.00 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.08 sec)

mysql> select queue_wait('q4m_t2');
+----------------------+
| queue_wait('q4m_t2') |
+----------------------+
|                    1 | 
+----------------------+
1 row in set (0.07 sec)

mysql> select queue_abort();
+---------------+
| queue_abort() |
+---------------+
|             1 | 
+---------------+
1 row in set (0.00 sec)

mysql> select count(*) from q4m_t2;
+----------+
| count(*) |
+----------+
|     9881 | 
+----------+
1 row in set (0.00 sec)


9883 件

queue_wait() # owner モードに移行。

queue_wait() # 既に owner モード。(1)

queue_wait() # 上に同じ。(2)

queue_abort() # owner モードを abort 終了(3)

9881 件 # 2件処理された。(3件でも0件でもない)


となる。(3) で取得した分は queue_abort() でキューに返却されるが、(1), (2) は返却されないのだ。将来の実装予定として、一括 wait() が挙げられていたが、おそらく 一括 wait() で取得したデータは、queue_abort() すると一括でキューに戻ることになるのだと思う。


以上簡単な検証でした。