MySQL AUTO_INCREMENT 要点记录

参考:

[MySQL Cookbook(Edition 2)] Chaper 11 Generating and Using Sequences

[MySQL 5.1  参考手册]

google

 

1. AUTO_INCREMENT 列定义

1) 语法:

CREATE TABLE xxx

(

...

id INT UNSIGNED NOT NULL AUTO_INCREMENT,

PRIMARY KEY (id)

or

UNIQUE (id)

...

)

 

SERIAL是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的一个别名。

在整数列定义中,SERIAL DEFAULT VALUE是NOT NULL AUTO_INCREMENT UNIQUE的一个别名。

 

2) 能定义为AUTO_INCREMENT的列类型:整数类型。

3) UNSIGNED作用:将序列的取值范围增加一倍,

如TINYINT取值范围为-128~127,未指定UNSIGNED序列值为1~127,指定后则序列值为1~255。

4) AUTO_INCREMENT列必须被索引化。

5) MyISAM是支持含有AUTO_INCREMENT列的表的最佳引擎。

 

2. AUTO_INCREMENT 列值

1) 最大值取决于它所使用的整数类型。

2) 序列值的重用(含AUTO_INCREMENT 列的表数据被删除后所产生的场景):

a) 空洞值(如表中已有记录1,2,3,4,5, 删除了2, 则形成了2这个空洞值):无论何种表引擎,均不会重用。

b) 顶端值(如表中已有记录1,2,3,4,5, 则5是顶端值,然后删除了5):BDB会重用(下一个序列值为5),MyISAM、InnoDB不会重用(下一个序列值为6)。

 

3) 序列值的查询:

a) 通过数据库函数: LAST_INSERT_ID() 这个返回值基于服务器的每一个客户端连接。

b) 通过JDBC API: Java: getLastInsertID() 方法:

long seq = ((com.mysql.jdbc.Statement) s).getLastInsertID();

or

long seq = ((com.mysql.jdbc.PreparedStatement) s).getLastInsertID(); 

注意事项:

a) 生成和获取AUTO_INCREMENT操作在同一个MySQL连接内,否则将会得到0。

b) 客户端序列值的有效性与每一条语句相关,而不仅仅由生成AUTO_INCREMENT值的语句决定。

使用如下原则可以避免错误:当生成一个不会马上使用的序列值,可以先保存到一个变量中。

4) 序列值的范围扩展:

a) 如果列值类型是有符号的,改为UNSIGNED。

b) 如果已经是UNSIGNED并不是最大的整数类型(BIGINT),则变更列类型为最大的整数类型。

5) 序列值的重建:

从表中删除这一列,然后再添加回去,MySQL会将列值重新序列化为一个连续序列。

 

6) 指定步长、偏移量:

a) 全局配置方式:

在 my.ini 中增加以下配置项:

auto_increment_increment=n

auto_increment_offset=x

 

Replication时,为防止auto_increment列值重复 ,则是在 my.cnf 中增加以上2个配置项:

如在A服务器的my.cnf设置如下: 
auto_increment_offset = 1 
auto_increment_increment = 2 
则A的auto_increment字段产生的数值是:1, 3, 5, 7, ... 

在B服务器的my.cnf设置如下: 
auto_increment_offset = 2 
auto_increment_increment = 2 
则B的auto_increment字段产生的数值是:2, 4, 6, 8, ... 

b) 针对某表:

CREATE TABLE 加上 AUTO_INCREMENT=n  

or

ALTER TABLE  AUTO_INCREMENT=n  

如果表是非MyISAM或InnoDB引擎,则可以这样:

插入具有序列值n-1的“假”行,然后在插入了一行或多行“真”数据后删除这个“假”行。

 

3. AUTO_INCREMENT 其他应用场景:
1) 复合主键:

昆虫采集表:

CREATE TABLE bug
(
  id      INT UNSIGNED NOT NULL AUTO_INCREMENT,
  name    VARCHAR(30) NOT NULL, # type of bug
  date    DATE NOT NULL,        # date collected
  origin  VARCHAR(30) NOT NULL, # where collected
  PRIMARY KEY (name, id)
);

插入一些数据,然后使用 order by 查询表中数据,可以看到MySQL为每一个唯一的name值创建了一个独立的序列:

 

mysql> SELECT * FROM bug ORDER BY name, id;
+----+-----------+------------+-------------------+
| id | name      | date       | origin            |
+----+-----------+------------+-------------------+
|  1 | ant       | 2006-10-07 | kitchen           |
|  2 | ant       | 2006-10-07 | front yard        |
|  3 | ant       | 2006-10-07 | front yard        |
|  4 | ant       | 2006-10-11 | garden            |
|  1 | beetle    | 2006-10-07 | basement          |
|  2 | beetle    | 2006-10-08 | front yard        |
|  1 | cricket   | 2006-10-08 | garage            |
|  2 | cricket   | 2006-10-10 | basement          |
|  3 | cricket   | 2006-10-11 | garden            |
|  1 | honeybee  | 2006-10-08 | back yard         |
|  2 | honeybee  | 2006-10-11 | garden            |
|  1 | millipede | 2006-10-07 | basement          |
|  1 | termite   | 2006-10-09 | kitchen woodwork  |
|  2 | termite   | 2006-10-11 | bathroom woodwork |
+----+-----------+------------+-------------------+

 

 

2) 计数器:
采用一个计数器占用一行的序列生成机制。

 

INSERT语句中加上 ON DUPLICATE KEY UPDATE

例:

INSERT INTO tbl (col, num) VALUES('test', LAST_INSERT_ID(n))

ON DUPLICATE KEY UPDATE num = LAST_INSERT_ID(num+n);


3) 循环序列:

使用 division 和 modulo 操作符生成循环元素。

业务场景:

假设你正在生产药品或汽车零件,你必须通过批号跟踪所有商品,如果以后发现了产品问题,要求召回售出的某一批产品。假设你把12个产品包装为1盒,6盒包装为1箱。

这种情况下,产品编号为3个部分:单品编号(1到12)、盒编号(1到6)、1个批号(从1到任意值)。

根据序列编号生成箱、盒和单品编号的公式如下:

unit_num = ((seq - 1) % 12) + 1

box_num = (int ((seq - 1) / 12) % 6) + 1

case_num = int ((seq - 1)/(6 * 12)) + 1

下表说明了序列值与对应的箱、盒、单品编号之间的关系:

 

seqcaseboxunit
1111
121112
13121
721612
73211
1442612

 

 

4. Oracle MySQL 的 sequence 和 AUTO_INCREMENT 互转:

MySQL---ORACLE序列解决方案

MySQL全局序列的实现方式(待实践研究):

1) sequence表:缺点:可能会成为性能瓶颈。

2) Flickr:与sequence表方式类似,但较好地解决了性能瓶颈和单点问题。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值