慢速自动增量重置
我有很多表,由于某些原因,我需要在应用程序启动时调整这些表的自动增量值。
我尝试这样做:
mysql> select max(id) from item;
+----------+
| max(id) |
+----------+
| 97972232 |
+----------+
1 row in set (0.05 sec)
mysql> alter table item auto_increment=1097972232;
在另一个会话中:
afrolov@A1-DB1:~$ mysql -u root -e "show processlist" | grep auto_increment
472196 root localhost test Query 39 copy to tmp table alter table item auto_increment=1097972232
MySQL 正在开始重建表!为什么MySQL需要这么做呢?如何在调整 auto_increment 值时避免重建巨大的表?
MySQL 5.0、InnoDB。
表定义:
CREATE TABLE `item` (
`id` bigint(20) NOT NULL auto_increment,
`item_res_id` int(11) NOT NULL default '0',
`stack_count` int(11) NOT NULL default '0',
`position` int(11) NOT NULL default '0',
`place` varchar(15) NOT NULL default '',
`counter` int(11) NOT NULL default '-1',
`is_bound` tinyint(4) NOT NULL default '0',
`remove_time` bigint(20) NOT NULL default '-1',
`rune_res_id` int(11) default NULL,
`rune_id` bigint(20) default NULL,
`avatar_id` bigint(20) NOT NULL,
`rune_slot_res_id` int(11) default NULL,
`is_cursed` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `avatar_id` (`avatar_id`,`place`,`position`),
UNIQUE KEY `rune_id` (`rune_id`),
KEY `idx_item_res_id` (`item_res_id`)
) ENGINE=InnoDB AUTO_INCREMENT=97972233 DEFAULT CHARSET=utf8;
关于为什么我必须这样做。长话短说,我想解决有关在服务器重新启动时重置 auto_increment 值的 mysql innodb 问题。有时我们将表中的行复制到另一个表,并且必须保持行 ID 不变。当我们向 table1 添加一行(例如 id=1),将行复制到 table2 ,从 table1 中删除行并重新启动 MySQL 时,那么当我们在 table1 中创建新的一行时,该行也将获得 id=1 。因此,如果我们必须将行复制到 table2,我们就会违反唯一约束。我们已经有很多代码,很难全部重写。调整自动增量值似乎是解决此问题的最简单方法。
添加:
MySQL 5.5 - 都一样:(
I have a lot of tables and because of some reasons I need to adjust auto increment value for this tables on application startup.
I try to do this:
mysql> select max(id) from item;
+----------+
| max(id) |
+----------+
| 97972232 |
+----------+
1 row in set (0.05 sec)
mysql> alter table item auto_increment=1097972232;
In another session:
afrolov@A1-DB1:~$ mysql -u root -e "show processlist" | grep auto_increment
472196 root localhost test Query 39 copy to tmp table alter table item auto_increment=1097972232
MySQL is starting to rebuild table! Why MySQL need to do it? How can I avoid rebuilding huge tables while adjusting auto_increment value?
MySQL 5.0, InnoDB.
Table definition:
CREATE TABLE `item` (
`id` bigint(20) NOT NULL auto_increment,
`item_res_id` int(11) NOT NULL default '0',
`stack_count` int(11) NOT NULL default '0',
`position` int(11) NOT NULL default '0',
`place` varchar(15) NOT NULL default '',
`counter` int(11) NOT NULL default '-1',
`is_bound` tinyint(4) NOT NULL default '0',
`remove_time` bigint(20) NOT NULL default '-1',
`rune_res_id` int(11) default NULL,
`rune_id` bigint(20) default NULL,
`avatar_id` bigint(20) NOT NULL,
`rune_slot_res_id` int(11) default NULL,
`is_cursed` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `avatar_id` (`avatar_id`,`place`,`position`),
UNIQUE KEY `rune_id` (`rune_id`),
KEY `idx_item_res_id` (`item_res_id`)
) ENGINE=InnoDB AUTO_INCREMENT=97972233 DEFAULT CHARSET=utf8;
About why I have to do this. Long story short i want to workaround mysql innodb issue about reseting auto_increment value on server restart. Sometimes we copy rows from our tables to another tables and we must keep rows id unchanged. When we add one row (with id=1 for example) to table1, copy row to table2 , delete row from table1 and restart MySQL, then when we create a new one row in table1 this row will get id=1 too. So if we will have to copy row to table2 we get unique constraint violation. We already have a lot of code and it will be hard to rewrite it all. Adjusting autoincrement value seems the easiest way to fix this problem.
Added:
MySQL 5.5 - all the same :(
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
只需将需要
auto_increment_id-1
的临时记录添加到每个表中,然后删除记录,快速简单,但可能太脏了
示例:
insert into item set id=1097972232-1;
执行后,下一个 auto_increment 将是 1097972232,这就是你想要的
这可以避免缓慢
simply add a temporary record that has desired
auto_increment_id-1
to each table,and remove the record after that, quick and easy, but probably too dirty
example:
insert into item set id=1097972232-1;
after the execution, the next auto_increment will be 1097972232, which is what you desired
this can avoid slowness
这是 MySQL 的记录“功能”:
http://dev.mysql.com/doc/refman/5.0 /en/alter-table.html
MySQL 5.1 和 5.5 支持更多一些带有临时表的 alter table 操作,但是更改 auto_increment 没有记录为其中之一。
无论如何,为什么需要更改 auto_increment 值?这不是你应该经常做的事情。
This is a documented "feature" of MySQL:
http://dev.mysql.com/doc/refman/5.0/en/alter-table.html
MySQL 5.1 and 5.5 support a few more alter table operations w/o a temporary table, but changing the auto_increment is not documented to be one of those.
Why do you need to change the auto_increment value, anyway? This isn't something you should be doing routinely.
没有简单的方法可以绕过 MySQL 中的 AUTO_INCRMENT 属性默认行为,即使您找到了方法,我也不建议您这样做,因为这是遇到以下问题的最佳方法短期内出现的问题。
AUTO_INCRMENT
值不应在生产环境中调整或重置。解决您的问题的一种可能的解决方案可能是稍微对您的模型进行非规范化。我们的想法是将
AUTO_INCRMENT
字段移至侧表,您无需在其中复制或删除行。您所要做的就是在创建新项目时从该侧表获取新的 id 值,并在将行从一个表复制到另一个表时保留现有的 id 值。为了实现这一点,我们将使用一个触发器来为我们创建一个新的 id 并将其分配给我们的项目记录。项目表的 id 字段必须可以为空才能工作,因此我们必须用唯一索引替换主键。
此模型更改将对您的应用程序完全透明,因此您无需在应用程序代码中进行任何更改。
以下是一些示例脚本。假设我们的数据库中有两个项目表,其中有一些公共行,以及一些需要从第一个表移动到第二个表的行:
如果我们尝试将一些数据从一个表移动到另一个表,然后重新启动服务器,我们会遇到
AUTO_INCRMENT
值重置的问题。因此,我们将稍微修改我们的模型,如下所示:我们将分几个步骤来迁移我们的数据模型。以下迁移脚本中的 DDL 语句是使用 neXtep Designer IDE 生成的。
AUTO_INCRMENT
字段:AUTO_INCRMENT
属性之前,我们必须将现有 id 插入新表中:AUTO_INCRMENT
属性,并初始化其值以供将来插入:item1
和item2
表以用唯一索引替换主键,并引用 item_keys 表的主键:现在我们可以将数据从一个表移动到另一个表,保持 ids 不变,如果我们重新启动服务器上,
item_keys
中的AUTO_INCRMENT
值将保持不变。There is no simple way to get around the
AUTO_INCREMENT
attribute default behavior in MySQL, and even if you find a way, I wouldn't recommend you to do so, since it is the best way to run into problems in the short-term.AUTO_INCREMENT
values are not meant to be adjusted or reseted in a production environment.One possible solution to your problem could be to denormalize your model a little. The idea is to move the
AUTO_INCREMENT
field to a side table where you don't have to copy or delete rows. All you have to do then is to get a new id value from this side table when you create a new item, and keep the existing id value when you copy rows from one table to another.To achieve this we will use a trigger that will create a new id for us and assign it to our item record. The id field of the item table has to be nullable for this to work, so we have to replace the primary key by a unique index.
This model change would be completely transparent for your application, so you would have no change to make in your application code.
Here are some example scripts. Let's say we have two item tables in our database, with some common rows, and some rows that need to be moved from first table to second table:
If we try to move some data from one table to another and then restart your server, we will encounter the issue of
AUTO_INCREMENT
value reset. So we will slightly modify our model as follows:We will proceed in several steps to migrate our data model. The DDL statements in the following migration scripts have been generated using neXtep Designer IDE.
AUTO_INCREMENT
field:AUTO_INCREMENT
attribute, we must insert existing ids into our new table:AUTO_INCREMENT
attribute, and initialize its value for future inserts:item1
anditem2
tables to replace the primary key by a unique index, and reference the primary key of the item_keys table:Now we can move data from one table to another, keeping the ids unchanged, and if we restart the server, the
AUTO_INCREMENT
value in theitem_keys
will stay the same.如果您需要在两个或多个服务器之间维护唯一 ID,请不要使用这种每次重置 auto_increment 的 alter table 方法。更改增量的增量会更容易,以便每个服务器无需干预即可生成唯一的 ID。对于两台服务器,您设置一台从 0 开始,一台从 1 开始,增量为 2 - 之后一台将生成偶数 ID,另一台将生成赔率。对于 3 个或更多服务器,您只需将初始值设置为 0/1/2,增量为 3,对于 4 个服务器,初始值为 0/1/2/3,增量为 4,等等...
有关服务器端设置的详细信息,请参见此处:
http://dev.mysql.com/ doc/refman/5.1/en/replication-options-master.html#sysvar_auto_increment_increment
这样,您只需为每个服务器的每个表重置 auto_increment 一次,之后它们将自动处理唯一性问题。
If you need to maintain unique IDs between two or more servers, don't use this alter table method of resetting the auto_increment each time. It'd be easier to change the increment's increment so that each server will generate unique IDs without intervention. For two servers, you set one to start at 0 and one to start at 1, with an increment of 2 - afterward one will generate even IDs, the other will generate odds. With 3 or more servers, you just set the initial values to 0/1/2 with increments of 3, for four it's 0/1/2/3 with inc of 4, etc...
Details on the server-side settings here:
http://dev.mysql.com/doc/refman/5.1/en/replication-options-master.html#sysvar_auto_increment_increment
This way you only have to reset the auto_increment once per table per server, and afterward they'll take care of the uniqueness problem automatically.
不是吗:
?
来源
Isn't it :
?
Source