mysql - 应该使用哪种锁定方案和隔离级别来生成序列号?

标签 mysql

我想知道业界用于生成序列号的一般做法。

即从表中获取最大值。增加它并将其存储回去。

为了使其工作,应使用哪种隔离级别和/或锁定方案。

我认为可序列化应该可以正常工作。但它只会阻止对表的更新。仍然可以进行选择。因此,将更新的值可能相同。我们如何避免这种情况?

谢谢!

最佳答案

您在事务范围内所做的任何事情都受制于竞争条件。

因此,您为获取上次使用的值、增加它并将其存储在新行中而执行的任何 SQL 查询都意味着两个并发客户端可以获取相同的值并尝试使用它,从而导致重复键。

有几种解决方法:

  1. Locking.如果您使用 SELECT ... FOR UPDATE(如@Daniel Vassallo 所述)

  2. ,每个客户端都会在他们读取的行上设置独占锁
  3. Use auto-increment.这种机制保证没有竞争条件,因为新值的分配是在不考虑事务范围的情况下发生的。作为一个好处,没有两个并发客户端将获得相同的值。不过,这意味着回滚不会撤消值的分配。 LAST_INSERT_ID()函数返回当前 session 分配的最后一个自动增量值,即使其他并发客户端也在同一表或不同表中生成值。

  4. 使用外部解决方案。生成主键值不是使用 SQL,而是使用应用程序中的其他系统。您有责任防止竞争条件。例如,您可以使用计数信号量。

  5. 使用伪随机的唯一 ID。主键需要是唯一的,但不需要是单调递增的整数。有些人使用 UUID()函数生成一个随机的 128 位数字,几乎可以保证没有重复。但是您的主键必须使用更大的数据类型,例如 CHAR(36)BINARY(16) 并且不方便编写临时查询。

    SELECT * FROM MyTable WHERE id = '6ccd780c-baba-1026-9564-0040f4311e29';

您在评论中提到您“阅读了一些关于使用自动增量的负面信息”。当然,任何语言的任何特性都有做和不做的。这并不意味着我们不应该使用这些功能,而是意味着我们应该学习如何正确使用它们。

您能描述一下您对自动增量的担忧或任何负面影响吗?也许这个线程上的人可以解决这些问题。

关于mysql - 应该使用哪种锁定方案和隔离级别来生成序列号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3325458/

相关文章:

PHP/MySQL 查询字符限制?

PHP&MYSQL - 向数据库插入数据失败

mysql - 如何从 MySQL 控制台切换到新用户

mysql - Perl MySQL - 如何拆分搜索字符串并与 LIKE %$word1%$word2% "dynamically"匹配?

mysql - SEC_TO_TIME 时间错误

php - 处理MYSQL中的NA和空白

php - 如何根据今天的日期和截止日期选择行

php - 从 mysql 检索一条记录并将其存储在 PHP 的数组中

mysql - 如何在 Mysql 中计算 Count(*) 的总和

mysql - 在数据库中存储每次行程在每个州行驶的距离