作为注册新用户的一部分;我们从预编译列表(表)中为他们分配资源(在这种情况下,为Solr核心)。
如果有5个用户注册,则必须为他们分配5个 不同的内核 ;如果用户成功注册,则分配完成(请参见下面的说明)。
但是在现实世界中,并发注册新用户 竞争同一行,而不是选择不同的行
。如果X需要5秒钟来注册,则X的“持续时间”中的Y和Z的注册将失败,因为它们争用X的同一行。
问题: 即使在高并发率(例如每秒100次注册)下,如何使交易选择而没有争用?
table: User
user_id name core
1 Amy h1-c1
2 Anu h1-c1
3 Raj h1-c1
4 Ron h1-c2
5 Jon h1-c2
table: FreeCoreSlots
core_id core status
1 h1-c1 used
2 h1-c1 used
3 h1-c1 used
4 h1-c2 used
5 h1-c2 used #these went to above users already
6 h1-c2 free
7 h1-c2 free
8 h1-c2 free
9 h1-c2 free
伪代码(如果隔离了东西):
sql = SQLTransaction()
core_details = sql.get("select * from FreeCoreSlots limit 1")
sql.execute("update FreeCoreSlots set status = 'used' where id = {id}".format(
id = core_details["id"]))
sql.execute("insert into users (name,core) values ({name},{core})".format(
name = name,
id = core_details["id"]))
sql.commit()
如果第二次进行100次注册,则它们将 争夺第一行 ,FreeCoreSlots
并导致严重的失败。
有一个select … for更新,如InnoDB SELECT … FOR
UPDATE语句锁定表中的所有行作为解决方案,但它们似乎建议降低隔离度。这种方法正确吗?
我要问的问题是,为什么用户可能需要5秒钟才能完成。在START TRANSACTION
和之间COMMIT
应该只有几分之一秒。
为了防止FreeCoreSlots
再次将同一行分配给同一用途,您必须再次使用SELECT for UPDATE
。我认为锁定级别并不是真正的问题。设计数据库的下一个空闲行的FreeCoreSlots
方式实际上已锁定,直到完成事务为止。请在下面查看我的测试结果。而且我确实认为,即使对于每秒100个新用户来说,这仍然足够。但是,如果您甚至想克服这一点,则必须找到一种方法来锁定其中的另一个下一个空闲行FreeCoreSlots
给每个用户。不幸的是,没有“选择第一行,除非它有锁”的功能。也许改为使用一些随机或模数逻辑。但是,正如我已经说过的那样,即使对于不可思议的每秒100个新用户,我认为这也不应该是您的问题。如果我对此有错,请随时发表评论,我愿意再看一遍。
这是我的测试结果。默认的InnoDB锁定级别:不带的 可重复读取FOR UPDATE
。这样就行不通了。
User 1:
START TRANSACTION
SELECT * FROM FreeCoreSlots WHERE status = 'FREE' LIMIT 1 -- returns id 1
User 2:
START TRANSACTION
SELECT * FROM FreeCoreSlots WHERE status = 'FREE' LIMIT 1 -- also returns id 1 !!!
User 1:
UPDATE FreeCoreSlots SET status = 'USED' where ID = 1;
User 2:
UPDATE FreeCoreSlots SET status = 'USED' where ID = 1; -- WAITS !!!
User 1:
INSERT INTO user VALUES (...
COMMIT;
USER 2:
wait ends and updates also ID = 1 which is WRONG
锁定级别 可重复读取, 但带有FOR UPDATE
。这样就可以了。
User 1:
START TRANSACTION
SELECT * FROM FreeCoreSlots WHERE status = 'FREE' LIMIT 1 FOR UPDATE -- returns id 1
User 2:
START TRANSACTION
SELECT * FROM FreeCoreSlots WHERE status = 'FREE' LIMIT 1 FOR UPDATE -- WAITS
User 1:
UPDATE FreeCoreSlots SET status = 'USED' where ID = 1;
User 2:
still waits
User 1:
INSERT INTO user VALUES (...
COMMIT;
USER 2:
Gets back Id 2 from the select as the next free Id
问题内容: 我正在尝试选择mysql表中的重复行,它对我来说很好,但问题是它不是让我选择该查询中的所有字段,而是让我选择用作不同的字段名,让我写查询更好的了解 第一个工作正常 现在,当我尝试选择所有字段时,我最终会出现错误 我正在尝试选择最新的重复项,比如说ticket_id 127是行ID 7、8、9的3倍,因此我想选择一次,最新条目在这种情况下为9,这适用于所有其余项ticket_id的 任何
问题内容: 我在SQL数据库表中使用了带有2个字段的select Disctinct语句。这是我的代码。 并产生错误:。请帮忙 问题答案: 您在sql语句中只选择了一个列Author。BookCode不存在,因此也不会出现在数据集中。 将BookCode包含在Sql语句中,它将得到修复
问题内容: 我一直在尝试 HQL 和 Criteria的 不同组合,但我无法避免某些不必要的 联接 (在这两者中)和某些不必要的 选择 (在Criteria中)。 在我们的场景中, 段* 和 应用程序 实体之间具有 @ManyToMany 关系(导航是从段到应用程序)。 *** 首先,我尝试了以下 条件 : 威奇产生这个SQL: 如您所见, Criteria从APPLICATIONS选择列 ,我不
我一直在尝试HQL和Criteria的不同组合,但我无法避免一些不必要的连接(在两者中)和一些不必要选择(在Criteria中)。 在我们的场景中,我们在Segment和Application实体之间有@ManyTo的关系(导航是从Segment到应用程序)。 首先我尝试了这个标准: Wich 生成此 SQL: 正如您所看到的,Criteria从APPLICATION中选择列,我不想被选择。我还没
本文向大家介绍d3.js 不同的选择器,包括了d3.js 不同的选择器的使用技巧和注意事项,需要的朋友参考一下 示例 您可以使用不同的选择器选择元素: 按标签: "div" 按类别: ".class" 依编号: "#id" 按属性: "[color=blue]" 多个选择器(OR): "div1, div2, class1" 多个选择器(AND): "div1 div2 class1"
我有一个从XML映射的类。为了简单起见,让我们想象这个类是这样的: 现在,现有的代码中充满了像这样的方法: …等等。你肯定有这个想法。 我需要包含一个新的方法来从employee返回一个新的属性,但是由于我觉得这对mantain来说是可怕的,所以我拒绝在那里添加一个新的方法。我正在考虑使用action模式,以某种方式避免至少重复againg和for循环,但我不得不说,我找不到一个聪明的解决方案。