我们正在使用MySQL和InnoDB存储引擎和交易很多,而且我们遇到了一个问题:我们需要一种很好的方法来模拟MySQL中的Oracle SEQUENCE。要求是: - 并发支持 - 交易安全 - 最大性能(意味着最小化锁定和死锁)
我们不关心是否会使用某些值,即顺序中的间隙是否正常。有一种简单的方法可以通过创建一个带计数器的独立InnoDB表来实现这一点,但这意味着它将参与事务并引入锁和等待。我想尝试使用手动锁,任何其他想法或最佳实践的MyISAM表?
答案 0 :(得分:15)
如果自动增量不足以满足您的需求,您可以使用 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。
答案 1 :(得分:9)
UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();
答案 2 :(得分:5)
我们是一家高交易游戏公司,需要这些解决方案来满足我们的需求。 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";
答案 3 :(得分:0)
表上的MySQL Identity列不会处理这个吗?
CREATE TABLE table_name ( id INTEGER AUTO_INCREMENT PRIMARY KEY )
或者您是否希望将其用于除插入另一个表之外的其他内容?
如果您正在使用过程语言(而不仅仅是SQL)编写,那么另一个选项是创建一个包含单个整数(或长整数)值的表和一个锁定它的存储过程,从中选择它,递增它并在返回值之前将其解锁。
(注意 - 在返回值之前总是递增 - 如果有错误,它会最大化不重复的机会 - 或者将整个事物包装在事务中。)
然后,您将独立于主插入/更新调用它(因此它不会被调用机制自动创建的任何事务捕获),然后将其作为参数传递给您想要使用它的任何位置。
因为它与你正在做的其他东西无关,所以应该快速并避免锁定问题。即使你确实看到了由锁定引起的错误(除非你的数据库超载,否则你可能只是第二次/第三次调用它)。