4

我在 inndob 表上有一个不断的“选择...更新”查询流。

主要条件是它选择“column1”小于100的所有字段。

在后台有不断的插入,这可能涉及“column1”小于100的插入,但这不是问题。如果第一个更新选择错过了它,因为它发生在执行该查询时,或者在获取结果数组时,下一个将捕获它,我很高兴将第一个查询标记为丢失它,因为它是'为时已晚'。

如果我有 10 个这样的“选择更新”查询等待,因为 inndob 字段锁定,我应该自己处理它们的排队还是让数据库对其进行排序?我认为处理这个问题的正确方法是自己排队查询?

所以当脚本到达

$sql = "SELECT * FROM ... FOR UDPATE"

事先检查队列数组(?),如果队列数组不为空,则将此脚本调用放在最后的队列数组中,然后每隔几毫秒检查一次队列数组,直到它到达队列中的第 1 位?

我在这里的想法是否正确......重要的是我现在正确而不是稍后再回来

编辑:我可以添加什么来增加响应的可能性:)

4

1 回答 1

3

InnoDB 应该为您处理排队。如果有一个事务正在进行,相关行上的锁,然后第二个事务尝试使用另一个 SELECT FOR UPDATE 语句获取相同的锁,那么第二个语句将等到第一个事务提交。

你可以自己测试一下:

  1. 打开两个 bash shell 窗口,并在每个窗口中运行 mysql 客户端。
  2. START TRANSACTION在每个窗口中 运行。
  3. SELECT ... FOR UPDATE在第一个窗口中 发出 a 。
  4. 然后在第二个窗口中执行相同的操作,使用应与相同行重叠的 WHERE 子句。
  5. 在第一个窗口中,运行SHOW ENGINE INNODB STATUS并观察事务及其锁。您应该会看到输出包括以下内容:

    LIST OF TRANSACTIONS FOR EACH SESSION:
    ---TRANSACTION 3B17, ACTIVE 4 sec starting index read
    mysql tables in use 1, locked 1
    LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
    MySQL thread id 2, OS thread handle 0x7ff27ae2d700, query id 28 192.168.56.1 root Sending data
    select * from foo where id < 100 for update
    ------- TRX HAS BEEN WAITING 4 SEC FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 266 page no 3 n bits 72 index `PRIMARY` of table `test`.`foo` trx id 3B17 lock_mode X waiting
    ------------------
    TABLE LOCK table `test`.`foo` trx id 3B17 lock mode IX
    RECORD LOCKS space id 266 page no 3 n bits 72 index `PRIMARY` of table `test`.`foo` trx id 3B17 lock_mode X waiting
    ---TRANSACTION 3B16, ACTIVE 70 sec
    2 lock struct(s), heap size 376, 2 row lock(s)
    MySQL thread id 1, OS thread handle 0x7ff27ae6e700, query id 29 192.168.56.1 root
    show engine innodb status
    TABLE LOCK table `test`.`foo` trx id 3B16 lock mode IX
    RECORD LOCKS space id 266 page no 3 n bits 72 index `PRIMARY` of table `test`.`foo` trx id 3B16 lock_mode X
    

注意在上面,事务 3B16 持有锁,而事务 3B17 正在等待锁。

事务 3B16 显示它当前正在运行“显示引擎 innodb 状态”,但它仍然持有它在之前的 SELECT ... FOR UPDATE 中获得的锁。即使该语句完成,事务也没有完成,并且在事务完成时释放锁。

如果事务 3B17 等待的时间超过lock_wait_timeout几秒,并且第一个事务仍未提交或回滚,则等待语句放弃并产生此错误:

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
于 2013-05-14T23:09:00.810 回答