在使用MySQL时,若表中含自增字段(auto_increment类型),则向表中insert一条记录后,可以调用last_insert_id()来获得最近insert的那行记录的自增字段值
$mdb->lastInsertId();
但事实上,使用last_insert_id()时有很多注意事项,否则很容易踩到坑。
若在同一条insert语句中插入多行(如"insert into tbl_name (col_a, col_b) values ('aa', 'bb'), ('aaa', 'bbb')"这类SQL语句),则last_insert_id()返回的自增字段的"当前值"只在旧值的基础上加1,这与实际情况不符(表中的实际情况是自增字段值在旧值基础上加N)!
3. 假设用形如"INSERT ... ON DUPLICATE KEY UPDATE"的SQL语句更新表,此时,若该语句的实际作用是insert操作时,调用last_insert_id()会返回本次insert后自增字段的当前值;而若该语句的实际作用是update操作时,调用last_insert_id()返回的是自增字段的旧值,而非当前更新行的自增字段值,所以这个值无意义(因为调用last_insert_id()是想获取sql影响到的行的自增字段值进而做其它逻辑业务的,如果得到的值并非sql操作影响到的行对应的自增值,则这个值对业务来说无意义),按照MySQL手册的说明,若业务开发者想得到实际update操作影响到的行的自增值,可以用形如"INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;"的SQL语句来获取。
关于带参数的last_insert_id()函数的使用说明,可以参考本文第8条的说明。
若在SQL中显式指定自增字段的值,如假设某张表由两列(id, name)构成,其中id为自增类型,假设当前表中id值为2,那么,执行"insert into test_tbl (id, name) values (11, 'test3');"后,再执行"select last_insert_id()",可以发现,得到的结果依旧是2。也即,只有自增字段由mysql来分配时,last_insert_id()才可能得到正确的值;SQL中显式更新自增字段值时,last_insert_id()返回的值不可用!
如果sql语句执行出错,则调用last_insert_id()的值未定义。例如,若事务因执行出错回滚,则last_insert_id()的值不会恢复到事务执行前的那个值。
last_insert_id()的值是由MySQL server来维护的,而且是为每条连接维护独立的值,也即,某条连接调用last_insert_id()获取到的值是这条连接最近一次insert操作执行后的自增值,该值不会被其它连接的sql语句所影响。这个行为保证了不同的连接能正确地获取到它最近一次insert sql执行所插入的行的自增值,也就是说,last_insert_id()的值不需要通过加锁或事务机制来保证其在多连接场景下的正确性。
如果通过"insert ignore"语句尝试插入新纪录,假设由于unique key冲突导致插入不成功,则auto_increment计数器不会变化,根据MySQL手册的说明,此时调用last_insert_id()会返回0表示没有新行被插入。但我在MySQL 5.1.73版本上测试的结果显示,last_insert_id()只是维持旧值而已,并不会返回0。
8. last_insert_id(expr)的行为
若调用last_insert_id()时传入了参数,则它会将参数值返回给调用者,并记住这个值,下次调用不带参数的last_insert_id()时,仍会返回这个值。可以利用这个特性实现一个多用户安全的全局计数器,示例如下:
1) 先创建一张表
mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);
2) 每条连接执行下面的SQL语句来获取为其自动分配的全局唯一ID
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
mysql> SELECT LAST_INSERT_ID();
每次都会id+1
当然,上面给出的全局ID分配器只是一种思路,在实际工程实现中,频繁的update操作可能会造成系统瓶颈,可以参考PERCONA MYSQL PERFORMANCE BLOG这篇文章的优化思路(比如MySQL前面用cache抗read压力,通过delay update来减缓update压力)。
参考:

mysql LAST_INSERT_ID 使用与注意事项的更多相关文章

  1. mysql 创建表时注意事项

    mysql  创建表时注意事项 mysql 想必大家都不会陌生吧  是我学习中第一个接触的的数据库 已学习就很快上手的   这是一个关系型数据库  不懂什么是关系型数据库 啊哈哈哈  现在知道啦  因 ...

  2. MySQL数据库使用时注意事项

    MySQL数据库使用时注意事项 建表的角度上 1.合理安排表关系 2.尽量把固定长度的字段放在前面 3.尽量使用char 代替varchar 4.分表:水平分和垂直分 在使用sql语句的时候 1.尽量 ...

  3. mysql索引设计的注意事项

    mysql索引设计的注意事项 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过key_len确定究竟使用 ...

  4. mysql索引设计的注意事项(大量示例,收藏再看)

    mysql索引设计的注意事项(大量示例,收藏再看) 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过ke ...

  5. MySQL建立索引的注意事项

    对于大数据量的表格,尤其是百万行以上的数据表,一定要对其建立索引,否则查询速度极慢.(参考后面的测试结果)建立索引时需注意: MySQL的索引有两种:单列索引(即在某一列上建索引).多列组合索引(即在 ...

  6. mysql索引分类及注意事项

    MYSQL索引主要分为四类:主键索引,普通索引(聚合,非聚合),唯一索引,全文索引 全文索引,主要是针对对文件,文本的检索, 比如文章, 全文索引针对MyISAM有用. 索引的原理:利用二叉树(哈希表 ...

  7. 使用mysql索引技巧及注意事项

    一.索引的作用 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重. 在数据 ...

  8. mysql使用索引的注意事项

    使用索引的注意事项 使用索引时,有以下一些技巧和注意事项: 1.索引不会包含有NULL值的列 只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索 ...

  9. mysql LAST_INSERT_ID详解

    http://blog.sina.com.cn/s/blog_5b5460eb0100nwvo.html LAST_INSERT_ID() LAST_INSERT_ID(expr) 自动返回最后一个I ...

随机推荐

  1. 15.SpringMVC和Spring上下文关系(为什么SpringMVC可以调用到Spring)

    springmvc上下文继承于spring, 也就是springmvc的上下文可访问spring上下文,在springmvc的上下文中可取得spring bean. spring上下文是spring启 ...

  2. CentOS搭建svn服务器支持https访问

    在CentOS6.3 64位机器上配置SVN服务器,并设置只允许HTTPS连接,可以配置多个repos源,每个源都拥有自己的组和成员,用于权限控制. 安装相关软件 Apache yum install ...

  3. php dirname($path) 中文路径不对问题

    将$path中的\改为/ $dir=__FILE__;$dir = str_replace("\\","/", $dir);$dir=dirname($dir) ...

  4. October 12th 2016 Week 42nd Wednesday

    Passion is momentary; love is enduring. 激情短暂,真爱长久. What is love? And what is real love? We are alway ...

  5. gcc提供的原子操作函数

    gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作.其声明如下: type __sync_fetch_and_add (type *ptr, type ...

  6. mysql扩展库-1

    启用mysql扩展库 在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 可以通过 phpinfo() 查看当前php支持什么扩展库. 在sql扩展库中创建一 ...

  7. php 投票系统练习

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. Android Tab -- 使用ViewPager、PagerAdapter来实现

    原文地址:http://blog.csdn.net/crazy1235/article/details/42678877 效果:滑动切换,自动切换. 代码:https://github.com/ldb ...

  9. 服务器知识----IIS架设问题

    1,基本配置,应用程序池,路径等. 2,权限设置  Iuser  IIS_users 只读权限 3,isapi映射  framework安装目录下  运行 aspnet_regiis.exe -i 注 ...

  10. CLR via C#(10)-参数

    一. 命名参数.可选参数 命名参数和可选参数是在Visual C#2010中引入的新特性. 笨地儿我个瓜不兮兮的,今天才知道. 可选参数:定义方法时为参数设置默认值,调用该方法时可以省略为某些形参指定 ...