我想在一个事务请求中执行数据库的读取和条件创建或更新。
让我们以暴雪的《星际争霸》等游戏为例: 假设 Bob 想与随机的其他玩家进行决斗。 他只需点击“搜索按钮”,然后在查询其数据库后,服务器将创建一个新游戏,其中有 Bob,例如 Alice。
在此示例中,假设数据库包含 users
和 games
表。
这种情况可能发生在以下步骤中:
- 爱丽丝想玩,点击“搜索按钮”。
- 假设此时没有任何游戏,将在
games
中添加一个新行(使用src_user
FK 给Alice,以及dst_user
FK 到NULL
)。 - 然后,Bob 来了,点击“搜索按钮”。
- 此刻,有 Alice 的游戏请求,因此 Bob 可以加入。
dst_user
FK 然后可以从NULL
切换到 Bob。
这个系统看起来不错。但我担心的是,由于用户数量庞大,如果搜索和更新都不是原子的,可能会有一些同步更新。
我的意思是,如果 Bob 和 Oscar 同时在寻找游戏,SQL 服务器首先会为两个用户回答 Alice 的游戏请求(这是 games
中的一行 table )。然后,Bob 和 Oscar 都会尝试更新线路以加入游戏。
为了防止这种情况,是否可以在一个查询中处理所有这些(尽可能保持与 MySQL 和 PostgreSQL 的兼容性)?
PS:数据库结构可能是这个...
CREATE TABLE users (
id SERIAL PRIMARY KEY,
);
CREATE TABLE games (
id SERIAL PRIMARY KEY,
src_user_id BIGINT UNSIGNED NOT NULL,
-- if NULL, the game is not ready...
dst_user_id BIGINT UNSIGNED NULL,
FOREIGN KEY (src_user_id) REFERENCES users(id),
FOREIGN KEY (dst_user_id) REFERENCES users(id)
);
最佳答案
我会使用这样的查询:
update games set dst_user_id=? where id=? and dst_user_id is null;
这样我可以确保只有当没有其他用户加入时才会更新一行。要检查游戏是否成功创建,我会检查更新的行数 - 大多数数据库引擎都支持这一点。
关于mysql - 原子读取和条件创建或更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32936749/