InnoDB表写锁,但允许读取

问题描述:

我有一个表COMMANDS,用户同时插入数据。InnoDB表写锁,但允许读取

每插入一次,我必须做一些(耗时)的计算并将结果保存到另一个表RESULTS

与此同时所有用户也从COMMANDS读取数据。

我的问题是:

后新$command插入,我使用所有的行该表在我的计算。每行都会影响计算,也可能会影响以前的$commands,因为我想锁定此表以获取新插入,直到进行当前计算并保存结果。但我也不想阻止其他用户查看当前状态COMMANDS

不久之后,我想锁定表格进行写入而不锁定读取。

我使用InnoDB引擎。我读了一些关于锁定的文档,但我完全困惑。

共享和排它锁,意图锁定,差距锁...

看来愚蠢的,但目前我使用类似下面

public function storeNewCommand($command){ 

    // $busy_flag is an app level global that can be read by all user sessions 

    if($busy_flag){ 
     usleep(10000); 
     return $this->storeNewCommand($command); 
    } 

    $busy_flag = true; //(lock) 

    /* 
    ...insert new $command to COMMANDS 

    ...do calculations using all comands including last one 

    ...store results in RESULTS 
    */ 

    $busy_flag = false; //(unlock) 

} 

我知道必须有更好的和聪明的解决方案的机制这没有圈和睡觉。但我不知道使用哪一个。

+0

注意如何设置一个队列,这样就可以将“用户输入过程”从“保存到数据库过程”中分离出来,并控制如何在计算时避免插入新行。 – Alfabravo

+0

谢谢@Alfabravo我正在使用一些队列作业,但他们工作异步,并且对每个插入后的所有保存的命令的当前状态非常重要。所以我想在数据库级别阻塞插入,如果有一个ongoning计算。 – Jaxovee

+0

对我来说,模仿一个表级锁是错误的策略。不管用户如何,他们都应该通过相同的队列和相同的DAO发送他们的请求。 – Alfabravo

如果你可以做的长度小于lock_wait_timeout,其中默认为50秒,然后使用BEGIN ... COMMIT。 (个人而言,我将其限制为更像2秒,而不是50)。

否则,设计一些其他方法 - 有一个表,每作家荣誉,说你在这个“关键”部分”。它可能不需要比具有单行的1列或2列表格多得多。

当抓取该互斥锁时,一定要将提取,设置等封装在一个事务中,并对失败作出反应。获得锁定后,继续执行缓慢的操作。最后放开锁。

警告:如果发生崩溃或软件错误,释放锁的代码可能永远不会执行。因此,包含时间戳以及注意互斥体在“很长”时间内未被释放的情况是很好的。他们可以通过电子邮件向您发送有关问题并清除锁定的信息