设为首页 收藏本站
查看: 420|回复: 0

[经验分享] MySQL AUTO_INCREMENT 要点记录

[复制链接]

尚未签到

发表于 2016-9-20 10:53:42 | 显示全部楼层 |阅读模式
参考:

[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
  下表说明了序列值与对应的箱、盒、单品编号之间的关系:
  


seq
case
box
unit

1
1
1
1


12
1
1
12


13
1
2
1


72
1
6
12


73
2
1
1


144
2
6
12
  
  
  4. Oracle MySQL 的 sequence 和 AUTO_INCREMENT 互转:
  MySQL---ORACLE序列解决方案
  MySQL全局序列的实现方式(待实践研究):
  1) sequence表:缺点:可能会成为性能瓶颈。
  2) Flickr:与sequence表方式类似,但较好地解决了性能瓶颈和单点问题。
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-274897-1-1.html 上篇帖子: MySql 数据库入门讲解 下篇帖子: Testing MySQL Replication Connection
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表