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() すると一括でキューに戻ることになるのだと思う。
以上簡単な検証でした。