2016-12-30 59 views
1

目前,我们有一个票务管理系统,就像所有票务系统一样,它需要以循环方式将情况分配给座席。同时,代理可以应用自己的过滤逻辑并在其队列中工作。MySql逻辑优化

问题,

  1. 表与门票现在是非常大的,跨越超过1000万行。
  2. 一张票不应该分配给两个不同的用户。
  3. 为了解决上述问题,这是我们拥有的流量,
  4. 选择查询与过滤条件解雇,限制0,1
  5. 上述查询返回的行然后可以将选定基于ID和锁定更新。
  6. 最后我们开始更新,说用户X选择了这个案例。
  7. 虽然第3步执行其他用户无法获得相同的情况下锁,所以他们发射3.查询可能会多次获取下一个可用的情况。
  8. 随着用户数量的增加,在步骤4中这个时间越来越高。

我们尝试在第4步本身的查询中进行select更新,但它使整个查询变慢。假设这是因为select查询中有大量的行。

问题,

  • 是否有不同的方法,我们需要完全承担?
  • 会在存储过程中进行选择和更新以确保与选择更新然后更新相同的结果?

P.S - 我问了同样的问题stackexchange。

+0

是否需要锁定该行。你也可以在没有锁的情况下执行它:通过SELECT读取一行并获得旧用户,并在UPDATE处添加条件WHERE ... AND user = old_user。所以如果更新一行,那么所有其他进程都可以获得这张票 –

回答

0

问题是您正在尝试使用MySQL级别锁定来确保票证不能分配给多个人。这样就无法检测用户是否锁定了票证。

我将通过向票据表中添加2个与锁相关的字段来实现应用级锁:应用锁的时间戳和告诉你哪个用户持有锁的用户ID字段。与锁相关的字段可以保存在另一个表格中(例如购物车可以用于此目的)。

当用户选择了票,然后尝试用一个有条件更新语句来更新这些锁定字段:代替...

update tickets 
set lock_time=now(), lock_user=... 
where ticket_id=... and lock_time is null 

值由您的应用程序提供。 lock_time is null条件是为了确保如果票证已被其他用户选中,则后面的用户不会覆盖该锁定。更新语句后检查受影响的行数。如果是1,则当前用户获得锁定。如果它是0,则其他人锁定票证。

如果您在另一个表中具有锁定数据,那么在该表中的票证ID字段上放置一个唯一的限制,并使用insert获取一个锁。如果插入成功,则获取锁。如果失败,则另一个用户已锁定票证。

锁定通常会持续数分钟,之后您的应用程序必须释放锁定(将锁定字段设置为null或从其他表中删除锁定记录)。