多线程调用生成主键流水号存储过程产生主键冲突问题解决方案

遇到开发多线程测试插入数据的时候发现主键冲突问题

问题具体描述如下:

--------------------------------------------------------------

调用Procedure_insert

Procedure_insert

Begin

Call procedure(获取流水号)

Insert into table values(流水号作为id,其他列);

End

流水号存储过程:

Update 统计表 统计字段+1

Update 统计表 最终流水号 set类型+年月日+补零位+统计字段

Select 最终流水号; //作为主键

---------------------------------------------------------------

问题:多线程并发会生成的主键冲突

写个java多线程调用一下测试,发现当加上事务便不会出现问题,无论在存储过程加还是代码过程加事务都可以,看似问题就这么解决了,方案如下:

-----------------------------------------------------------------

程序代码  con.begin 开始事务

调用Procedure_insert

Procedure_insert

Begin

Call procedure(获取流水号)

Insert into table values(流水号作为id,其他列);

End

程序代码 con.commit();

流水号存储过程:

Update 统计表 统计字段+1

Update 统计表 最终流水号 set类型+年月日+补零位+统计字段

Select 最终流水号; //作为主键

-----------------------------------------------------------------

不过问题究竟发生在哪里,既然是主键冲突,并且只有在多线程并发下,没有事务的情况下才会发生,那么单独测试一下生成主键的存储过程,如下:

发现问题了,果然是多线程下没加事务造成的

既然测试出来结果,也知道了解决方法,貌似就解决了,那么又有新的问题了,为什么不加事务多线程调用生成流水号的存储过程会产生相同的主键呢?

和我的流水号生成方式有关

procedure

begin

update 语句;

update 语句 拼接;

select 语句;

end

由于多线程并发,导致更新流水号时是异步的,第一个语句可能同时执行了,然后再执行第二句,导致最终只会产生最后一个主键;总之生成主键的过程并不是一个整体,导致了生成同一个主键。

时间: 2024-11-03 01:47:21

多线程调用生成主键流水号存储过程产生主键冲突问题解决方案的相关文章

mysql 生成流水号 存储过程 订单编号

用存储过程生成流水号是很常用的,这里以生成订单编号的流水号作为示例.(新的一天的流水号从1开始,如:今天的订单编号是CD2013010900014,下一个订单编号将是CD2013010900015:明天的订单编号将从CD2013011000001开始) 生成规则:    2位前缀+年月日+5位流水号     或者 2位前缀+年月日时分+5位流水号     或者 2位前缀+年月日时分秒+5位流水号. 测试订单表(test_orders): 1 CREATE TABLE `test_orders`

MySQL主键自动生成和生成器表以及JPA主键映射

MySQL主键自动生成 表设计 MySQL有许多主键生成策略,其中很常见的一种是自动生成.一般情况下,主键类型是BIGINT UNSIGNED,自动生成主键的关键词是AUTO_INCREMENT. CREATE TABLE Stock ( id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, NO VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, price DECIMAL(6,2) N

NDK使用技巧、多线程调用注意、ndk中的工具使用

//NDK 使用技巧和多线程调用注意 //http://www.ibm.com/search/csass/search/?q=ndk&sn=dw&lang=zh&cc=CN&en=utf&hpp=20&dws=cndw&lo=zh void demo(JNIEnv* env, jobject thiz) { //这JNI接口指针可以存储,但只在当前线程仍然是有效的. /* A JNI environment pointer (JNIEnv*) is

多线程调用COM组件的体会(CoInitialize)(转)

原文转自 https://www.cnblogs.com/manors/archive/2010/05/17/COM_Initialize_STA_MTA.html 与设备打交道时,我们经常用到COM组件,比如音视频设备(麦克风.播放器.摄像头等). 调用任何COM组件之前,你必须首先初始化COM套件环境,即调用CoInitialize或CoInitializeEx.COM套件环境在线程的生存周期内有效,线程退出前需要调用CoUninitialize释放COM套件. 所谓COM套件,实际上是微软

将表里的数据批量生成INSERT语句的存储过程 继续增强版

文章继续 桦仔兄的文章 将表里的数据批量生成INSERT语句的存储过程 增强版 继续增强... 本来打算将该内容回复于桦仔兄的文章的下面的,但是不知为何博客园就是不让提交!.... 所以在这里贴出来吧,算作继续增加文章中解决的:根据查询条件自动生成插入脚本的需求,其实这种需求还是蛮常见的. 本文着重解决了文中的脚本的schema问题,给调整了下,现在脚本能自动识别出不同的schema下同名的表的语句 修改后脚本如下: -- Author: <桦仔> -- Blog: <http://ww

MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)

测试缘由 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了拿实际的案例来说服他,所以准备做一个详细的测试.   作为互联网公司,一定有用户表,而且用户表UC_USER基本会有百万记录,所以在这个表基础上准测试数据来进行测试.            测试过程是目前我想到的多方位的常用的几种类型的sql进行测试,当然可能不太完善,欢迎大家留言提出更加完善的测试方

主键、自增主键、主键索引、唯一索引概念区别与性能区别

概念区别: 主键:指字段唯一不为空值的列. 主键索引:指的就是主键,主键没有明确的概念定义,主键既是约束,也是索引,主键是索引的一种,是唯一索引的特殊类型.创建主键的时候,数据库默认会为主键创建一个唯一索引. 自增主键:字段类型为数字.自增.并且是主键. 唯一索引:索引列的值必须唯一,但允许有空值.主键是唯一索引,这样说没错.但反火来说唯一索引也是主键就错误了,因为唯一索引允许空值,主键不允许有空值,所以不能说唯一索引也是主键. 性能区别: 通过测试,发现主键.自增主键.唯一索引的查询效率不一样

数据库中超键、候选键、主键的区分

超键(super key):在关系中能唯一标识元组的属性集称为关系模式的超键候选键(candidate key):不含有多余属性的超键称为候选键主键(primary key):用户选作元组标识的一个候选键程序主键 比如一个小范围的所有人,没有重名的,考虑以下属性:身份证.姓名.性别.年龄. 身份证 唯一 所以是一个超键姓名 唯一 所以是一个超键(姓名,性别) 唯一 所以是一个超键(姓名,性别,年龄) 唯一 所以是一个超键--这里可以看出,超键的组合是唯一的,但可能不是最小唯一的 身份证 唯一而且

oracle 主键删除,联合主键的创建

1,主键的删除 ALTER TABLE TABLENAME DROP PRIMARY_KEY 执行上面的SQL可以删除主键:如果不成功可以用 ALTER TABLE TABLENAME DROP CONSTRAINTS COLUMN CASCADE; --删除约束 ALTER TABLE TABLENAME DISABLE PRIMARY_COLUMN ; --设置被设置为主键的列为无效 DROP INDEX INDEX_NAME; --删除主键索引 2,查看主键约束 SELECT * FROM