增量计数器mysql

时间:2012-07-24 21:00:46

标签: php mysql myisam

我的问题非常简单,但答案可能很棘手。

我在PHP中,我想手动管理我的对象的唯一ID。 棘手的是管理原子性。我不希望2个元素获得相同的ID。

“元素”分组在“组”中。在每个组中,我希望元素ID从1开始,并逐渐增长该组中的每个插入。

我的第一个解决方案是在“Groups”表中有一个“lastID”列:

CREATE TABLE groups ( id INT AUTO_INCREMENT, lastId INT )
CREATE TABLE elements ( myId INT, multiple values ...)

为了避免许多具有相同ID的元素,我必须更新lastId并在原子SQL查询中选择它。

之后,检索到一个,我有一个无法再次选择的唯一ID,我可以插入我的元素。

我的问题是如何解决大胆的部分?我的数据库是带有MyISAM引擎的MySQL,因此没有事务支持。

UPDATE groups 
SET lastId = lastId + 1 
WHERE id = 42

SELECT lastId 
FROM groups
WHERE id = 42

有没有比这两个请求更原子的东西?

由于

3 个答案:

答案 0 :(得分:3)

UPDATE groups SET lastId = last_insert_id(lastId + 1)

然后您可以使用

获取新ID
SELECT last_insert_id()

last_insert_id与参数一起使用将存储该值,并在以后调用时将其返回 这种生成自动编号的方法最适用于只有几行的MyISAM表(MyISAM总是锁定整个表)。它还具有在事务持续期间不锁定表的好处(如果它是InnoDB表,则会发生这种情况)。

这来自MySQL manual

  

如果expr作为LAST_INSERT_ID()的参数给出,则该值为   参数由函数返回,并作为下一个记住   LAST_INSERT_ID()返回的值。这可以用来模拟   序列:

     

创建一个表来保存序列计数器并对其进行初始化:

CREATE TABLE sequence (id INT NOT NULL); 
INSERT INTO sequence VALUES (0); 
  

使用该表生成如下序列号:

UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID(); 
  

UPDATE语句递增序列计数器   并导致下一次调用LAST_INSERT_ID()以返回更新的   值。 SELECT语句检索该值。该   mysql_insert_id()C API函数也可用于获取值。   请参见第21.8.3.37节“mysql_insert_id()”。

     

您可以在不调用LAST_INSERT_ID()的情况下生成序列,但是   这种方式使用函数的效用是ID值   在服务器中维护为最后自动生成的值。它   是多用户安全的,因为多个客户端可以发出UPDATE   声明并使用SELECT语句获取自己的序列值   (或mysql_insert_id()),不影响或受其他影响   生成自己的序列值的客户端。

答案 1 :(得分:3)

一个选项是让你使用漂亮的MyISAM功能,让每个组的auto_increment值递增。

CREATE UNIQUE INDEX elements_ix1 ON元素(groupId,myID)

myID INT NOT NULL AUTO_INCREMENT

这比涉及更新单独表格的任何内容都更“原子”。请注意,这仅适用于MyISAM,而不适用于InnoDB。


摘自http://dev.mysql.com/doc/refman/5.1/en/example-auto-increment.html

MyISAM备注

对于MyISAM表,您可以在多列索引中的辅助列上指定AUTO_INCREMENT。在这种情况下,AUTO_INCREMENT列的生成值计算为MAX(auto_increment_column)+ 1 WHERE prefix = given-prefix。当您想要将数据放入有序组时,这非常有用。

答案 2 :(得分:0)

我认为你的MySQL安装也有InnoDB引擎支持交易。您只需要更改表的引擎类型。