首先了解 LAST_INSERT_ID

  • LAST_INSERT_ID 有自己的存储空间,能存一个数字
  • 不带参数时返回最近insert的那行记录的自增字段值。带参数时会将自己存储的数字刷成参数给定的值

结合使用样例来看:

-- 这种情况是正常情况,LAST_INSERT_ID 输出值会增加
INSERT INTO `advertise_ipad` (`path`, `status`) VALUES ('testValue', 1);
SELECT LAST_INSERT_ID(); -- 输出1 -- 如果主动赋值了 AUTO_INCREMENT 字段,则输出值不会增加
INSERT INTO `advertise_ipad` (`id`, `path`, `status`) VALUES ('', 'testValue', 1);
SELECT LAST_INSERT_ID(); -- 输出1
INSERT INTO `advertise_ipad` (`path`, `status`) VALUES ('testValue', 1); -- 这时 AUTO_INCREMENT 被刷成100,如果再执行不带id的插入,下一个id会为101,LAST_INSERT_ID 也变成101
SELECT LAST_INSERT_ID(); -- 输出101 -- 如果主动赋值了 AUTO_INCREMENT 字段,且值比当前自增值小,不会改变 LAST_INSERT_ID 的结果
INSERT INTO `advertise_ipad` (`id`, `path`, `status`) VALUES ('', 'testValue', 1);
SELECT LAST_INSERT_ID(); -- 输出101
INSERT INTO `advertise_ipad` (`path`, `status`) VALUES ('testValue', 1); -- 这时 AUTO_INCREMENT 还是101,不会被60影响,再执行不带id的插入,下一个id和 LAST_INSERT_ID 会为102
SELECT LAST_INSERT_ID(); -- 输出102 -- 执行批量插入,虽然插入了103、104、105,三条记录,但 LAST_INSERT_ID 会返回第一个,即103
INSERT INTO `advertise_ipad` (`path`, `status`) VALUES ('testValue', 1), ('testValue', 1), ('testValue', 1);
SELECT LAST_INSERT_ID(); -- 输出103
INSERT INTO `advertise_ipad` (`path`, `status`) VALUES ('testValue', 1); -- 再插入一条记录,由于自增已经到了105,下一行会变成106,LAST_INSERT_ID 也变成106
SELECT LAST_INSERT_ID(); -- 输出106 -- 如果执行带参数的 LAST_INSERT_ID 方法,则会保存下来
SELECT LAST_INSERT_ID(600);
SELECT LAST_INSERT_ID(); -- 输出600
INSERT INTO `advertise_ipad` (`path`, `status`) VALUES ('testValue', 1); -- 再插入一条记录,由于自增还是106,下一行会变成107,LAST_INSERT_ID 也变成107
SELECT LAST_INSERT_ID(); -- 输出107

函数很简单

为了实现便于不同业务访问的id生成器,我们需要一个管理不同维度id的table,比如

CREATE TABLE `tbl_id_factory` (
`id_type` tinyint(3) unsigned NOT NULL,
`id_value` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建mysql函数来实现

CREATEFUNCTION `next_id`(id_type_index TINYINT) RETURNS bigint(20) DETERMINISTIC
BEGIN
UPDATE tbl_id_factory SET id_value = LAST_INSERT_ID(id_value+1) WHERE id_type = id_type_index;
RETURN LAST_INSERT_ID();
END

在上层调用时只需 SELECT next_id(业务类型) 即可

第三行的 LAST_INSERT_ID(id_value+1) 实际上将其值刷成 当前业务自增值+1,然后第四行返回。这里 LAST_INSERT_ID 函数起到中间变量的作用,当下一个业务访问时,LAST_INSERT_ID 又被刷成另一个业务的自增值+1,这需要 LAST_INSERT_ID 方法线程安全,文档中是这么说的

The value of mysql_insert_id() is affected only by statements issued within the current client connection. It is not affected by statements issued by other clients.

参考文档:https://dev.mysql.com/doc/refman/8.0/en/mysql-insert-id.html

mysql利用LAST_INSERT_ID实现id生成器的更多相关文章

  1. 常用的分布式ID生成器

    为何需要分布式ID生成器 **本人博客网站 **IT小神 www.itxiaoshen.com **拿我们系统常用Mysql数据库来说,在之前的单体架构基本是单库结构,每个业务表的ID一般从1增,通过 ...

  2. 分布式全局ID生成器原理剖析及非常齐全开源方案应用示例

    为何需要分布式ID生成器 **本人博客网站 **IT小神 www.itxiaoshen.com **拿我们系统常用Mysql数据库来说,在之前的单体架构基本是单库结构,每个业务表的ID一般从1增,通过 ...

  3. id 生成器介绍

    背景介绍 在一般的业务场景中, 初始的时候简单的自增数(比如MySQL 自增键)就可以很好的满足需求, 不过随着业务的发展和驱动, 尤其是在分布式的场景中, 如何生成全局的唯一 id 便成了需要慎重考 ...

  4. 如何快速开发一个支持高效、高并发的分布式ID生成器

    ID生成器是指能产生不重复ID服务的程序,在后台开发过程中,尤其是分布式服务.微服务程序开发过程中,经常会用到,例如,为用户的每个请求产生一个唯一ID.为每个消息产生一个ID等等,ID生成器也是进行无 ...

  5. 分布式ID生成器解决方案

    一.分布式系统带来ID生成挑战 在复杂的系统中,往往需要对大量的数据如订单,账户进行标识,以一个有意义的有序的序列号来作为全局唯一的ID; 而分布式系统中我们对ID生成器要求又有哪些呢? 全局唯一性: ...

  6. 百度开源的分布式 id 生成器

    UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器.UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于d ...

  7. 百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题

    UidGenerator是百度开源的Java语言实现,基于Snowflake算法的唯一ID生成器.而且,它非常适合虚拟环境,比如:Docker.另外,它通过消费未来时间克服了雪花算法的并发限制.Uid ...

  8. go语言实现分布式id生成器

    本文:https://chai2010.cn/advanced-go-programming-book/ch6-cloud/ch6-01-dist-id.html 分布式id生成器 有时我们需要能够生 ...

  9. 分布式唯一ID生成器

    在应用程序中,经常需要全局唯一的ID作为数据库主键.如何生成全局唯一ID? 首先,需要确定全局唯一ID是整型还是字符串?如果是字符串,那么现有的UUID就完全满足需求,不需要额外的工作.缺点是字符串作 ...

随机推荐

  1. 爬虫之进阶 基于twisted实现自制简易scrapy框架(便于对scrapy源码的理解)

    1.调度器 class Scheduler(object): """调度器""" def __init__(self, engine): & ...

  2. form表单中$_FILES数组的使用

    <form enctype="multipart/form-data" action="upload.php" method="post&quo ...

  3. Linux samba多用户挂载

    samba 多用户挂载 通过multiuser挂载选项,使用基于密码验证和cifscreds实现访问控制在默认情况下,samba共享挂载后,是通过挂载时的验证来实现对挂载资源的访问控制.通过新的mul ...

  4. (1)Linux常用的运维平台和工具

    运维工程师使用的运维平台和工具包括: Web服务器:apache.tomcat.nginx.lighttpd 监控:nagios.ganglia.cacti.zabbix 自动部署:ansible.s ...

  5. BootStrap布局组件

    BootStrap字体图标(Glyphicons) BootStrap下拉菜单:下拉菜单是可以切换的,是以列表格式显示链接的上下文菜单. 类 描述 .dropdown 指定下拉菜单 .dropdown ...

  6. 获取网页title(还有一坑未填)

    def getTitle(self,url): #get title title = 'time out' try: self.res = requests.get(url,timeout=5) so ...

  7. C#编码问题以及C#往Mysql插数据编码问题

    C#将字符转换成utf8编码 GB321编码转换   public static string get_uft8(string unicodeString) { UTF8Encoding utf8 = ...

  8. IDEA 上 Tigase8.0 源代码编译运行

    Tigase交流群 :310790965 一些小伙伴们经常问Tigase8 check下来的源代码怎么跑起来,因为我不能及时一 一回答,所以还是写个博文来演示一下吧,一般针对新手而言,老手的话,就跳过 ...

  9. 网址导航18A

    [导航] hao268 百度导航 泡泡导航 35Q网址导航 [名站] 百度 网易 腾讯 新华 中新 凤凰 [邮箱] 163邮箱 126邮箱 Yeah邮箱 QQ邮箱 阿里邮箱 189邮箱 [新闻] 联合 ...

  10. Eclipse 中 Maven 项目默认JDK版本为1.5 的解决方法

    在 Eclipse 中 Maven project 的默认 JDK 版本是 1.5, 如果不在 settings.xml 或者 pom.xml 中显示的指出 JDK 版本,每次 右键项目--> ...