views:

364

answers:

2

I am a user of a some host company which serves my MySql database. Due to their replication problem, the autoincrement values increses by 10, which seems to be a common problem.

My question is how can I simulate (safely) autoincrement feature so that the column have an consecutive ID?

My idea was to implement some sequence mechanism to solve my problem, but I do not know if it is a best option. I had found such a code snipset over the web:

DELIMITER ;;

DROP TABLE IF EXISTS `sequence`;;
CREATE TABLE `sequence` (
  `name` CHAR(16) NOT NULL,
  `value` BIGINT UNSIGNED NOT NULL,
  PRIMARY KEY  (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;;

DROP FUNCTION IF EXISTS `nextval`;
CREATE FUNCTION `nextval`(thename CHAR(16) CHARSET latin1)
RETURNS BIGINT UNSIGNED
MODIFIES SQL DATA
SQL SECURITY DEFINER
BEGIN
  INSERT INTO `sequence` 
    SET `name`=thename, 
        `value`=(@val:=@@auto_increment_offset)+@@auto_increment_increment
   ON DUPLICATE KEY 
    UPDATE `value`=(@val:=`value`)+@@auto_increment_increment;
  RETURN @val;
END ;;

DELIMITER ;

which seems quite all correct. My second question is if this solution is concurrent-safe? Of course INSERT statement is, but what about ON DUPLICATE KEY update?

Thanks!

+5  A: 

Why do you need to have it in the first place?

Even with auto_increment_increment == 1 you are not guaranteed, that the autoincrement field in the table will have consecutive values (what if the rows are deleted, hmm?).

With autoincrement you are simply guaranteed by the db engine, that the field will be unique, nothing else, really.

EDIT: I want to reiterate: In my opinion, it is not a good idea to assume things like concurrent values of an autoincrement column, because it is going to bite you later.

EDIT2: Anyway, this can be "solved" by an "on insert" trigger

create trigger "sequence_b_ins" before insert on `sequence`
for each row
begin
    NEW.id = select max(id)+1 from `sequence`;
end

Or something along these lines (sorry, not tested)

shylent
Yes, You are right. I'm not depending on the consecutivity of this autoincrement column, however for my client it is useful to have this number "almost always" consecutive.
vnx
Well, in my book, "almost always" means, basically, "never". This is not always true, but for this particular case, it, in my opinion (of course), is.
shylent
Thanks for your reply, I am going to reconsider my problem having in mind your words.
vnx
I am sorry if I sounded too harsh, but I was bitten really hard by my own assumptions (especially when dealing with the databases). In my experience, if something is guaranteed (as in "the uniqueness of the value in an autoincremented column is guaranteed"), then you can build your logic around that guarantee. If it is not guaranteed, then the best thing is to disregard it completely, as if it doesn't exist at all (such as the consecutivity of the values in an autoincremented column), rather then have to write ugly hacks later when it turns out that your assumption is wrong in some way.
shylent
A: 

Another option would be to use a stored proc to do the insert and have it either select max id from your table or keep another table with the current id being used and update as id's are used.

Myles
Right, this is second part of my question. Could you give me a hint if the code attached is concurrent-safe? It is an issue for me.
vnx