MariaDB社区

标题: 请大家帮忙解决一个奇怪的锁争用问题 [打印本页]

作者: mdmdmd    时间: 2010-9-23 00:11
标题: 请大家帮忙解决一个奇怪的锁争用问题
大家好。
问题大致是这样的:
MySQL版本是5.0,操作系统是debian。
有两个Table,一个是users(用户表),另一个是userdata(用户数据)。
users表的主键是UID,类型为int。
userdata表的主键是DataID,是个自增列,同时有个列UID,是users表中UID列的外键,另外,对列UID和另一个列Category建立了索引。
两个表都为InnoDB,结构大致为:
create table users(
      UID int primary key,
      ### other columns.....
) engine = innodb;
create table userdata(
      DataID int auto_increment primary key,
      UID int,
      Category int,
      ### other columns.....
      Key `Index_UID`(`UID`),
      key `Index_Category`(`Category`),
      constraint `FK_userdata_UID_users_UID` foreign key (`UID`) references `users` (`UID`) on delete cascade
) engine = innodb;
### other tables.....

我的需求是:
我的系统是一个高并发的、大数据量的系统.
我需要在userdata中找出指定的用户当前拥有哪些数据,再根据其当前拥有的数据判断应该给该用户增加、删除、更新哪些数据。
为了保证用来判断的数据的正确性,需要在每次查询数据前对数据进行加锁,待更新完数据后才释放锁。
整个操作在一个transaction中进行。
步骤如下:
(1):创建transaction : Trans
      select * from users where UID = xxx for update;
      返回Trans
(2):使用(1)中返回的Trans
      select * from userdata where UID = xxx and category in (c1, c2, c3);
(3):根据(2)中返回的数据判断需要增加、删除、更新一些数据,同样使用Trans
      update userdata ....
      update userdata ....
      insert userdata ....
      insert userdata ....
      delete userdata where DataID in (x1, x2, x3...);
      ### update other tables ....
      ### insert other tables ....
      ### delete other tables ....
(4):以上步骤若成功执行,则 commit Trans,否则rollback Trans。

以上代码在少用户量的环境下测试的时候没什么问题,但在大用户量的情况下却出现大量的锁等待,并有死锁的情况发生。
很多锁等待发生在select * from users where UID = xxx for update 语句处。

请各位帮忙分析一下以上逻辑存在什么问题,为何会有这么多的锁等待并发生死锁呢?
又或者各位有什么更好的实现逻辑?

谢谢。

作者: kider    时间: 2010-9-25 11:07
你更新的是userdata表,不用给user表加锁的呀...
还有能不放在Trans中的尽量提取出来。
作者: mdmdmd    时间: 2010-9-25 11:15
因为还需要更新其它的Table,并且很有可能不在一个DB中,
所以对users表加锁。
如果对userdata表加锁的话,很容易引发死锁。
作者: mdmdmd    时间: 2010-9-25 11:19
另外,Transaction是必须的,
有大量的逻辑需要处理,并且必要时需要回滚。
作者: kider    时间: 2010-9-25 16:45
你没有体会我的意思
如果你不交互,只是一次性提取user表信息,应该是不用加锁
要不就把外键去了试试(这里只是怀疑)...
作者: mdmdmd    时间: 2010-9-25 17:08
对Users表加锁的用意是为了每次对UserData表(及其它表)中的数据检索时都得到正确的结果,
需要根据UserData表中的数据(及用户在其它表中的数据)来判断应该接下来执行哪些操作。
经测试验证,外键并不会影响锁。
作者: kider    时间: 2010-9-26 09:37
那么对user加锁,然后执行后续N步操作,而后续N步操作需要较长时间,然后你又是大并发,既然你这么肯定逻辑没有问题和要改进的地方,又不能切碎,等待你的只能是糟糕的情况了...




欢迎光临 MariaDB社区 (http://123.56.88.72/) Powered by Discuz! X3.2