简体   繁体   English

增量计数器mysql

[英]incremental counter mysql

My question is pretty simple but answer might be tricky. 我的问题很简单,但答案可能很棘手。

I'm in PHP and I want to manage manually a unique ID for my objects. 我在使用PHP,并且想手动管理对象的唯一ID。 What is tricky is to manage atomicity. 棘手的是管理原子性。 I dont want that 2 elements get the same ID. 我不希望2个元素具有相同的ID。

"Elements" are grouped in "Groups". “元素”在“组”中分组。 In each group I want elements ID starting from 1 and grow incrementally for each insert in that group. 在每个组中,我希望元素ID从1开始,并对该组中的每个插入进行递增。

My first solution is to have a "lastID" column in the table "Groups" : 我的第一个解决方案是在“ Groups”表中有一个“ lastID”列:

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

In order to avoid many elements with the same ID, I have to update lastId and select it in an atomic SQL Query. 为了避免许多具有相同ID的元素,我必须更新lastId并在原子SQL查询中选择它。

After that, one retrieved, I have a unique ID that can't be picked again and I can insert my element. 之后,检索到一个,我有一个唯一的ID,无法再次选择它,并且可以插入我的元素。

My question is how to solve the bold part ? 我的问题是如何解决粗体部分? My database is MySQL with MyISAM engine so there is no transaction support. 我的数据库是带有MyISAM引擎的MySQL,因此没有事务支持。

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

SELECT lastId 
FROM groups
WHERE id = 42

Is there something more atomic than these 2 requests ? 还有什么比这两个请求更原子的?

Thanks 谢谢

UPDATE groups SET lastId = last_insert_id(lastId + 1)

and then you can get your new id with 然后您可以使用

SELECT last_insert_id()

Using last_insert_id with a parameter will store the value and return it when you call it later. last_insert_id与参数一起使用将存储该值,并在以后调用它时将其返回。
This method of generating autonumbers works best with MyISAM tables having only a few rows (MyISAM always locks the entire table). 这种生成自动编号的方法最适用于只有几行的MyISAM表(MyISAM始终锁定整个表)。 It also has the benefit of not locking the table for the duration of the transaction (which will happen if it is an InnoDB table). 它还具有在事务期间不锁定表的优点(如果它是InnoDB表,则会发生此情况)。

This is from the MySQL manual : 这是从MySQL手册

If expr is given as an argument to LAST_INSERT_ID(), the value of the argument is returned by the function and is remembered as the next value to be returned by LAST_INSERT_ID(). 如果将expr作为LAST_INSERT_ID()的参数提供,则该参数的值将由函数返回,并被记住为LAST_INSERT_ID()返回的下一个值。 This can be used to simulate sequences: 这可以用来模拟序列:

Create a table to hold the sequence counter and initialize it: 创建一个表来保存序列计数器并对其进行初始化:

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

Use the table to generate sequence numbers like this: 使用该表生成如下的序列号:

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

The UPDATE statement increments the sequence counter and causes the next call to LAST_INSERT_ID() to return the updated value. UPDATE语句增加序列计数器的值,并使对LAST_INSERT_ID()的下一次调用返回更新后的值。 The SELECT statement retrieves that value. SELECT语句检索该值。 The mysql_insert_id() C API function can also be used to get the value. mysql_insert_id()C API函数也可用于获取值。 See Section 21.8.3.37, “mysql_insert_id()”. 请参见第21.8.3.37节“ mysql_insert_id()”。

You can generate sequences without calling LAST_INSERT_ID(), but the utility of using the function this way is that the ID value is maintained in the server as the last automatically generated value. 您可以生成序列而无需调用LAST_INSERT_ID(),但是以这种方式使用该函数的实用工具是将ID值作为最后一个自动生成的值保存在服务器中。 It is multi-user safe because multiple clients can issue the UPDATE statement and get their own sequence value with the SELECT statement (or mysql_insert_id()), without affecting or being affected by other clients that generate their own sequence values. 这是多用户安全的,因为多个客户端可以发出UPDATE语句并使用SELECT语句(或mysql_insert_id())获得自己的序列值,而不会影响或受到生成自己序列值的其他客户端的影响。

One option is for you to use the nifty MyISAM feature that let's auto_increment values be incremented for each group. 一种选择是让您使用漂亮的MyISAM功能,让我们为每个组增加auto_increment值。

CREATE UNIQUE INDEX elements_ix1 ON elements (groupId, myID) 创建唯一索引elements_ix1 ON元素(groupId,myID)

myID INT NOT NULL AUTO_INCREMENT myID INT非空AUTO_INCREMENT

That's more "atomic" than anything that involves updating a separate table. 这比涉及更新单独表的任何事情都更“原子”。 Note that this only works for MyISAM, not InnoDB. 请注意,这仅适用于MyISAM,不适用于InnoDB。


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

MyISAM Notes MyISAM笔记

For MyISAM tables, you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. 对于MyISAM表,可以在多列索引的第二列上指定AUTO_INCREMENT。 In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. 在这种情况下,将为AUTO_INCREMENT列生成的值计算为MAX(auto_increment_column)+ 1 WHERE prefix = given-prefix。 This is useful when you want to put data into ordered groups. 当您要将数据放入有序组中时,这很有用。

I would assume your MySQL installation also has InnoDB engine which does support transactions. 我假设您的MySQL安装还具有支持事务的InnoDB引擎。 You just need to change the engine type of you tables. 您只需要更改表的引擎类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM