我的问题非常简单,但答案可能很棘手。
我在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
有没有比这两个请求更原子的东西?
由于
答案 0 :(得分:3)
UPDATE groups SET lastId = last_insert_id(lastId + 1)
然后您可以使用
获取新IDSELECT 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引擎支持交易。您只需要更改表的引擎类型。