MYSQL InnoDB 自增序列回降

本文探讨了MySQL InnoDB引擎下自增序列的回降问题,分析了在未删除子表关联数据情况下,新数据与旧数据关联导致的问题,并解释了自增序列计数器的工作原理。同时,提到了事务回滚可能引起的序列跳值现象。

自增序列回降

开发时遇到的一个问题

设计:

某业务数据库设计包含两张表,主表A和子表B,B有A的主键ID作为业务外键(未在mysql中建立外键)。开发时设计删除A表中的数据并未删除B表中的关联数据。

问题:

运行一段时间后发现新插入的A表数据会和B表未删除数据关联,即新插入的A的主键,在B中已存在外键关联。

原因:

MYSQL InnoDB 的自增序列计数器是存在内存中的,如果数据库重启服务,序列计数器会消失,mysql会在下次插入数据之前,查找本表中该列的最大值,以该值初始化计数器,然后继续自增。

解决:

还是老老实实删除子表数据吧。。

 

ps:如果发生事物回滚等操作会导致序列跳值现象。mysql只保证自增,不保证连续。

参考资料:https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html#innodb-auto-increment-initialization

### 自序列的实现方式 自序列是一种严格递的数字序列,广泛用于生成唯一标识符。在数据库和编程中,可以通过多种方式实现自序列。 #### 数据库中的自序列实现 在关系型数据库中,如 MySQL 和 Oracle,自序列通常通过表字段属性或专门的序列对象来实现。 1. **MySQL 中的自序列** 在 MySQL 中,可以通过设置表字段为 `AUTO_INCREMENT` 来实现自序列[^2]。例如: ```sql CREATE TABLE example ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) ); ``` 此外,也可以通过创建一张序列表并使用存储过程或函数来管理多组序列[^3]。例如: ```sql DROP TABLE IF EXISTS sequence; CREATE TABLE sequence ( name VARCHAR(50) NOT NULL COMMENT '序列名称', current_value BIGINT NOT NULL COMMENT '序列当前值', increment INT NOT NULL DEFAULT 1 COMMENT '序列步长', PRIMARY KEY (name) ) ENGINE=InnoDB; INSERT INTO sequence VALUES ('seq1', 0, 1); ``` 使用函数获取序列值时,需注意并发安全性[^3]。例如: ```sql DELIMITER $$ CREATE FUNCTION `get_sequence`(seq_name VARCHAR(50)) RETURNS BIGINT DETERMINISTIC BEGIN UPDATE sequence SET current_value = last_insert_id(current_value + increment) WHERE name = seq_name; RETURN last_insert_id(); END $$ DELIMITER ; ``` 2. **Oracle 中的自序列** Oracle 提供了专门的序列对象(Sequence)来生成自值[^4]。例如: ```sql CREATE SEQUENCE seq_example START WITH 1 INCREMENT BY 1; CREATE TABLE example ( id NUMBER DEFAULT seq_example.NEXTVAL PRIMARY KEY, name VARCHAR2(50) ); ``` #### 编程中的自序列实现 在编程语言中,可以结合锁机制或分布式算法实现自序列。 1. **Java 中的自序列** 在高并发场景下,可以通过原子类(如 `AtomicInteger` 或 `AtomicLong`)实现线程安全的自序列[^1]。例如: ```java import java.util.concurrent.atomic.AtomicLong; public class SequenceGenerator { private AtomicLong counter = new AtomicLong(0); public long getNextValue() { return counter.incrementAndGet(); } } ``` 2. **Python 中的自序列** 在 Python 中,可以使用线程锁(`threading.Lock`)确保自操作的安全性。例如: ```python import threading class SequenceGenerator: def __init__(self): self.counter = 0 self.lock = threading.Lock() def get_next_value(self): with self.lock: self.counter += 1 return self.counter ``` #### 总结 无论是数据库还是编程语言,自序列的实现都需要考虑并发安全性。数据库提供了内置机制(如 `AUTO_INCREMENT` 和 Sequence 对象),而编程语言则依赖于同步工具(如锁或原子类)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值