在 MySQL/InnoDB 中模拟自动增量

发布于 2024-09-10 08:14:38 字数 145 浏览 4 评论 0原文

假设我要

条件

  1. 使用 MySQL/InnoDB 模拟 MySQL/InnoDB
  2. 中的自动增量ID 字段没有唯一索引,也不是 PK

是否可以仅使用程序逻辑来模拟,而不使用表级锁。 谢谢。

Assume I am going to emulate auto-increment in MySQL/InnoDB

Conditions

  1. Using MySQL/InnoDB
  2. The ID field don't have unique index, nor it is a PK

Is it possible to emulate only using program logics, without table level lock.
Thanks.

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

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

发布评论

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

评论(4

逆光下的微笑 2024-09-17 08:14:39

使用序列表和触发器 - 像这样:

drop table if exists users_seq;

create table users_seq
(
next_seq_id int unsigned not null default 0
)engine = innodb;

drop table if exists users;

create table users
(
user_id int unsigned not null primary key,
username varchar(32) not null
)engine = innodb;

insert into users_seq values (0);

delimiter #

create trigger users_before_ins_trig before insert on users
for each row
begin

declare id int unsigned default 0;

  select next_seq_id + 1 into id from users_seq;

  set new.user_id = id;

  update users_seq set next_seq_id = id;

end#

delimiter ;

insert into users (username) values ('f00'),('bar'),('bish'),('bash'),('bosh');

select * from users;
select * from users_seq;

insert into users (username) values ('newbie');

select * from users;
select * from users_seq;

Use a sequence table and a trigger - something like this:

drop table if exists users_seq;

create table users_seq
(
next_seq_id int unsigned not null default 0
)engine = innodb;

drop table if exists users;

create table users
(
user_id int unsigned not null primary key,
username varchar(32) not null
)engine = innodb;

insert into users_seq values (0);

delimiter #

create trigger users_before_ins_trig before insert on users
for each row
begin

declare id int unsigned default 0;

  select next_seq_id + 1 into id from users_seq;

  set new.user_id = id;

  update users_seq set next_seq_id = id;

end#

delimiter ;

insert into users (username) values ('f00'),('bar'),('bish'),('bash'),('bosh');

select * from users;
select * from users_seq;

insert into users (username) values ('newbie');

select * from users;
select * from users_seq;
酒儿 2024-09-17 08:14:39
CREATE TABLE sequence (id INTEGER); -- possibbly add a name;
INSERT INTO sequence VALUES (1); -- starting value

SET AUTOCOMMIT=0;
START TRANSACTION;
UPDATE sequence SET id = LAST_INSERT_ID(id+1);
INSERT INTO actualtable (non_autoincrementing_key) VALUES (LAST_INSERT_ID());
COMMIT;

SELECT LAST_INSERT_ID(); 甚至是一个会话安全值,用于检查您获得的 ID。确保您的表支持事务,或者序列中的漏洞没有问题。

CREATE TABLE sequence (id INTEGER); -- possibbly add a name;
INSERT INTO sequence VALUES (1); -- starting value

SET AUTOCOMMIT=0;
START TRANSACTION;
UPDATE sequence SET id = LAST_INSERT_ID(id+1);
INSERT INTO actualtable (non_autoincrementing_key) VALUES (LAST_INSERT_ID());
COMMIT;

SELECT LAST_INSERT_ID(); Is even a session-safe value to check which ID you got. Be sure your table support transactions, or that holes in a sequence are no problem.

北音执念 2024-09-17 08:14:39

创建另一个具有单行单列的表,用于存储下一个 id 值。然后在原始表上创建一个插入触发器,增加第二个表中的值,获取该值,并将其用于第一个表上的 ID 列。您需要小心选择和更新的方式,以确保它们是原子的。

本质上,您是在 MySQL 中模拟 Oracle 序列。但这会导致序列表中的单行被锁定,因此这可能使其不适合您正在做的事情。

ETA:

另一个类似但可能性能更好的选项是创建第二个“序列”表,该表只有一个自动增量 PK 列,没有其他数据。让插入触发器在该表中插入一行,并使用从那里生成的 ID 来填充原始表中的 ID。然后让触发器或另一个进程定期删除序列表中的所有行以清理它。

Create another table with a single row and column that stores the next id value. Then create an insert trigger on the original table that increments the value in the second table, grabs it, and uses that for the ID column on the first table. You would need to be careful with the way you do the select and update to ensure they are atomic.

Essentially you are emulating an Oracle sequence in MySQL. It would cause a lock on single row in the sequence table though, so that may make it inappropriate for what you are doing.

ETA:

Another similar but maybe better performing option would be to create a second "sequence" table that just has a single auto-increment PK column and no other data. Have your insert trigger insert a row into that table and use the generated ID from there to populate the ID in the original table. Then either have the trigger or another process periodically delete all the rows from the sequence table to clean it up.

好久不见√ 2024-09-17 08:14:39

序列表需要有id作为自增PK

sequence table need to have id as the autoincrement PK

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