我们正在使用MySQL和InnoDB存储引擎和交易很多,而且我们遇到了一个问题:我们需要一种很好的方法来模拟MySQL中的Oracle SEQUENCE。要求是:   - 并发支持   - 交易安全   - 最大性能(意味着最小化锁定和死锁)

我们不关心是否会使用某些值,即顺序中的间隙是否正常。有一种简单的方法可以通过创建一个带计数器的独立InnoDB表来实现这一点,但这意味着它将参与事务并引入锁和等待。我想尝试使用手动锁,任何其他想法或最佳实践的MyISAM表?

有帮助吗?

解决方案

如果自动增量不足以满足您的需求,您可以使用 n 命名序列创建原子序列机制,如下所示:

创建一个表来存储序列:

CREATE TABLE sequence (
  seq_name varchar(20) unique not null,
  seq_current unsigned int not null
);

假设你在表格中有一行'foo',你可以原子地获得下一个序列id:

UPDATE sequence SET seq_current = (@next := seq_current + 1) WHERE seq_name = 'foo';
SELECT @next;

无需锁定。两个语句都需要在同一个会话中执行,以便在选择发生时实际定义局部变量@next。

其他提示

给出了正确的方法。 MySQL手册

UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

我们是一家高交易游戏公司,需要这些解决方案来满足我们的需求。 Oracle序列的一个特性也是可以设置的增量值。

该解决方案使用 DUPLICATE KEY

CREATE TABLE sequences (
  id BIGINT DEFAULT 1,
  name CHAR(20),
  increment TINYINT,
  UNIQUE KEY(name)
);

获取下一个索引:

使用存储过程或函数 sp_seq_next_val(VARCHAR)抽象以下内容:

INSERT INTO sequences (name) VALUES ("user_id") ON DUPLICATE KEY UPDATE id = id + increment;<br/>
SELECT id FROM sequences WHERE name = "user_id";

表上的MySQL Identity列不会处理这个吗?

CREATE TABLE table_name (    id INTEGER AUTO_INCREMENT PRIMARY KEY )

或者您是否希望将其用于除插入另一个表之外的其他内容?

如果您正在使用过程语言(而不仅仅是SQL)编写,那么另一个选项是创建一个包含单个整数(或长整数)值的表和一个锁定它的存储过程,从中选择它,递增它并在返回值之前将其解锁。

(注意 - 在返回值之前总是递增 - 如果有错误,它会最大化不重复的机会 - 或者将整个事物包装在事务中。)

然后,您将独立于主插入/更新调用它(因此它不会被调用机制自动创建的任何事务捕获),然后将其作为参数传递给您想要使用它的任何位置。

因为它与你正在做的其他东西无关,所以应该快速并避免锁定问题。即使你确实看到了由锁定引起的错误(除非你的数据库超载,否则你可能只是第二次/第三次调用它)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top