我正在尝试设计一个包含一组团队的数据库,每个团队最多可以有5名成员。最大值可能会改变,但对于这个问题,5就足够了。目前使用mysql构建,结构如下:
Table- Teams - teamid - Primary Key - [search criteria 1] - [search criteria 2] - [search criteria 3] - [other data]
Table- Accounts - accountid - Primary Key - [other data]
Table - Account Memberships - teamid - Primary Key, Foreign Key (Teams.teamid) - accountid - Primary Key, Foreign Key (Accounts.accountid)
系统将搜索与这3个条件完全匹配的团队。如果它找到一个或多个尚未填满的匹配项,它会将该用户添加到第一个匹配项。否则,它将使用指定的条件创建一个新团队,并将该用户添加为第一个成员。
我知道如何编写查询来搜索团队,以及如何计算团队中的成员。然而,我担心,如果几个用户同时尝试此操作,我将获得成员数量不正确的团队。例如,两个用户可能搜索相同的标准,最终被放置为同一团队的第五和第六个成员。
有没有一种方法可以编写我的查询或重构我的数据库设计,以防止竞争条件和/或原子地执行成员计数和成员更新?
发布于 2015-08-29 23:25:18
你可以尝试LOCK TABLES,然后阅读它,插入任何你想要的东西,然后是UNLOCK TABLES。这样,在读取和插入自己之前,几个进程将等待彼此完成,从而避免竞争。
发布于 2015-08-30 00:38:00
Uri2x的答案让我搜索了一些新的地方,我找到了一个查询,它可以在一个操作中完成我想要的功能:
INSERT INTO teammemberships (accountid, teamid) SELECT '[account id]', teams.teamid FROM teams LEFT JOIN teammemberships ON (teams.teamid = teammemberships.teamid) WHERE [search criteria] GROUP BY teams.teamid HAVING count(teammemberships.teamid) < 5 LIMIT 1;
这个查询剩下的唯一问题是,如果一个帐户试图加入第二个团队,并且他们的当前团队是由该select返回的团队,那么他们将得到一个重复的主键错误,而不是被添加到下一个可用团队。目前,我将用户限制在一个团队中,所以这应该是可以的。
发布于 2015-08-30 08:53:22
有没有一种方法可以让我编写我的查询或者重构我的数据库设计,以防止竞争条件和/或自动执行成员计数和成员更新?
不要使用LOCK TABLES,要使用Engine=InnoDB。
如果需要更新两个表,请执行以下操作
BEGIN;
UPDATE table1 ...;
UPDATE table2 ...;
COMMIT;并检查每一步的错误--死锁和其他错误可能会发生。
如果您在事务中还需要一个SELECT,那么您可能需要SELECT ... FOR UPDATE。
https://stackoverflow.com/questions/32287558
复制相似问题