我正在尝试设计一个包含一组团队的数据库,每个团队最多可以有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个条件的完全匹配的团队。如果找到一个或多个尚未填满的匹配项,则会将用户添加到第一个匹配项。否则,它将创建一个具有指定条件的新团队,并将用户添加为第一个成员。
我知道如何编写查询来搜索团队,并计算团队中的成员。但是,我很担心,如果有几个用户同时尝试此操作,我会让团队成员数量不正确。即2个用户可能会搜索相同的标准,并最终成为同一团队的第5和第6个成员。
有没有办法可以编写查询或重组数据库设计以防止竞争条件和/或原子地执行成员计数和成员更新?
答案 0 :(得分:0)
您可以尝试UNLOCK TABLES
然后阅读它,插入您想要的任何内容,然后my $i = 1;
s/position/ "position " . $i++ /eg;
。通过这种方式,几个进程将在读取和插入之前等待彼此完成,并且将避免竞争。
答案 1 :(得分:0)
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;
此查询唯一剩下的问题是,如果某个帐户正在尝试加入第二个团队,并且他们当前的团队是该选择返回的团队,他们将获得重复的主键错误,而不是添加到下一个可用的球队。目前我将用户限制在一个团队中,所以应该没问题。
答案 2 :(得分:0)
有没有办法可以编写查询或重组数据库设计以防止竞争条件和/或原子地执行成员计数和成员更新?
请勿使用LOCK TABLES
,请使用Engine=InnoDB
。
如果您需要更新两个表,请执行
BEGIN;
UPDATE table1 ...;
UPDATE table2 ...;
COMMIT;
并检查每一步的错误 - 可能发生死锁和其他错误。
如果您在交易中还需要SELECT
,则可能需要SELECT ... FOR UPDATE
。