SKIP LOCKED はサポートされていないが通ってしまう
TiDB 8.5 時点では SELECT ~ FOR UPDATE SKIP LOCKED はサポートされていません。
しかし、エラーにならずに通ってしまいます。
マニュアルには、「サポートされていない」とは書いてあるのですが、「無視する」とまでは書いてなさそう。
Unsupported features SKIP LOCKED syntax #18207
MySQL の場合
SKIP LOCKED は MySQL 8.0 でサポートされました。すでにロックされている行を除いて、ロックされてない行のみを返します(ロックを取ります)。
言うまでもありませんが、それ以前のバージョンでは文法エラーになります。
pk が 1 のレコードのロックを取ります。
mysql> SELECT * FROM tbl; +----+ | pk | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set (0.00 sec) mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tbl WHERE pk = 1 FOR UPDATE; +----+ | pk | +----+ | 1 | +----+ 1 row in set (0.00 sec)
pk が 1 以外のレコードが SELECT されます。
mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tbl FOR UPDATE SKIP LOCKED; +----+ | pk | +----+ | 2 | | 3 | +----+ 2 rows in set (0.00 sec)
TiDB の場合
同じように pk が 1 のレコードのロックを取ります。
mysql> BEGIN; Query OK, 0 rows affected (0.01 sec) mysql> SELECT * FROM tbl WHERE pk = 1 FOR UPDATE \G *************************** 1. row *************************** pk: 1 1 row in set (0.00 sec)
別のセッションで、SELECT ~ FOR UPDATE SKIP LOCKED を実行すると、pk が 1 のレコードも SELECT 出来てしまいます。
サポートしてないなら、エラーにしてほしい。。。。
mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) -- ちなみに、tidb_enable_noop_functions は OFF でも同じ mysql> SELECT * FROM tbl FOR UPDATE SKIP LOCKED \G *************************** 1. row *************************** pk: 1 *************************** 2. row *************************** pk: 2 *************************** 3. row *************************** pk: 3 3 rows in set (0.00 sec) -- 確かに pk = 1 の行はロックされている。 mysql> SELECT * FROM tbl WHERE pk = 1 FOR UPDATE \G ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
※ tidb_txn_mode = pessimistic (デフォルト) での動作確認しています。