MySql自增列增加10问题

发布于 2024-08-11 05:36:28 字数 890 浏览 9 评论 0原文

我是一家为我的 MySql 数据库提供服务的主机公司的用户。由于复制问题,自动增量值增加了 10,这似乎是一个常见问题。

我的问题是如何模拟(安全)自动增量功能以使列具有连续的 ID?

我的想法是实现一些序列机制来解决我的问题,但我不知道这是否是最佳选择。我在网上找到了这样的代码片段:

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 ;

这看起来完全正确。我的第二个问题是这个解决方案是否并发安全? INSERT语句当然是,但是ON DUPLICATE KEY更新呢?

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

新人笑 2024-08-18 05:36:28

为什么你首先需要拥有它?

即使使用 auto_increment_increment == 1,也不能保证表中的自动增量字段将具有连续的值(如果行被删除怎么办,嗯?)。

使用自动增量,数据库引擎可以简单地保证该字段是唯一的,没有别的,真的。

编辑:我想重申:在我看来,假设自动增量列的并发值之类的事情不是是一个好主意,因为它稍后会咬你。

来“解决” (抱歉,未测试)

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

EDIT2:无论如何,这可以通过“插入时”触发器或类似的东西

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)

瞄了个咪的 2024-08-18 05:36:28

另一种选择是使用存储过程进行插入,并让它从表中选择最大 id,或者保留另一个表,其中当前 id 正在使用,并在使用 id 时进行更新。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文