sql - 每个主键值都有某种 “different auto-increment indexes”

标签 sql database primary-key auto-increment

我有一个表,其中有一个id(具有自动增量的主键),uid(例如引用用户id的键)和其他一些我的东西问题并不重要。

我想为每个 uid 条目在 id 上创建(我们称之为)不同的自动增量键。

因此,我将添加一个 uid 10 的条目,并且该条目的 id 字段将具有 1,因为没有uid 中值为 10 的先前条目。我将添加一个 uid 4 的新条目,其 id 将是 3,因为我已经有两个 uid 4< 的条目.

...非常明显的解释,但我试图尽可能清晰地解释这个想法...清楚。

  1. 什么 SQL 引擎可以原生提供这样的功能? (不基于 Microsoft/Oracle)
  2. 如果没有,我怎样才能最好地复制它?也许是触发器?
  3. 此功能有更合适的名称吗?
  4. 如果您知道提供此类功能的非 SQL 数据库引擎,请无论如何命名它,我很好奇。

谢谢。

最佳答案

MySQL 的 MyISAM 引擎可以做到这一点。请参阅他们的手册,第 Using AUTO_INCREMENT 部分:

For MyISAM tables you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.

文档在该段落之后继续,展示了一个示例。

MySQL 中的 InnoDB 引擎不支持此功能,这很不幸,因为几乎在所有情况下最好使用 InnoDB。

在 INSERT 上不锁定表的情况下,您无法使用触发器(或任何仅限于事务范围的 SQL 语句)来模拟此行为。考虑以下操作序列:

  1. Mario 启动事务并为用户 4 插入新行。
  2. Bill 启动事务并为用户 4 插入新行。
  3. Mario 的 session 触发一个触发器来计算用户 4 的 MAX(id)+1。您得到 3。
  4. Bill 的 session 触发一个触发器来计算 MAX(id)。我得到了 3。
  5. Bill 的 session 完成了 INSERT 并提交。
  6. Mario 的 session 尝试完成他的 INSERT,但包含 (userid=4, id=3) 的行现在存在,因此 Mario 遇到主键冲突。

一般来说,如果没有某种同步,您就无法控制这些步骤的执行顺序。

解决这个问题的方法是:

  • 获取独占表锁。在尝试 INSERT 之前,锁定表。这对于防止并发 INSERT 创建 race condition 是必要的。就像上面的例子一样。有必要锁定整个表,因为您试图限制 INSERT,所以没有要锁定的特定行(如果您尝试使用 UPDATE 控制对给定行的访问,则可以仅锁定特定行)。但是锁定表会导致对表的访问变成串行访问,从而限制了吞吐量。

  • 在事务范围之外执行。以不会对两个并发事务隐藏的方式生成 ID 号。顺便说一句,这就是 AUTO_INCRMENT 的作用。两个并发 session 将各自获得一个唯一的 id 值,无论其执行顺序或提交顺序如何。但是跟踪每个用户 ID 最后生成的 ID 需要访问数据库或重复的数据存储。例如,每个用户 ID 一个 memcached 键,可以是 incremented atomically .

确保插入获得唯一的值相对容易。但很难确保它们会获得连续序数值。另请考虑:

  • 如果您插入事务然后回滚,会发生什么情况?您在该事务中分配了 id 值 3,然后我分配了值 4,因此如果您回滚并我提交,现在就会出现间隙。
  • 如果 INSERT 由于表上的其他约束(例如另一列不为 NULL)而失败,会发生什么情况?您也可以通过这种方式获得间隙。
  • 如果您删除了一行,是否需要为同一用户 ID 重新编号以下所有行?如果您使用该解决方案,这会对您的 memcached 条目产生什么影响?

关于sql - 每个主键值都有某种 “different auto-increment indexes”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7536573/

相关文章:

mysql - SQL女士2005 : Select a ID for a particular date where that date lies between fromdate and Todate

sql - 交换 SQL Server 中同一个表中两行的值

sql - 每 3 行生成行号

javascript - 当收到多个异步获取响应时,您如何选择您想要的响应(即用户请求的响应)?

c# - Entity Framework 在 SQL 查询中不使用 JOIN

database - HanaDB - : SELECT COUNT( * ) FROM dbtab 的复杂度

mysql - 创建一个依赖于sql中另一个字段值的唯一字段

java - 如何返回 java 中最后添加的项目的最后一个主键?

postgresql - 为什么插入主键不影响顺序?

mysql - 无法创建外键 MySQL Workbench