首先,非常感谢各位前辈的耐心指点,相信前辈们所指点之方式定是更好之处理方式,鉴于才识有限,尚未能领悟(感觉有点难);
经这两天的沉思,现已悟出一个的方法,采用传统之中规中矩sql语句并增加简易之逻辑判断,以procedure形式出现,将drpserialnum表之ID栏设为自增方式作为辅助,然后将procedure返回之结果进行相关处理并冠以部门编号,可解决当前问题;
此方法涉及之技术含量较低亦或其它问题,可能不是好的方案,其中不足之处,还望前辈们能够指出;
现在把这个procedure完整代码写于此,好让有类似需求人员有个参考:
注:
1.token组成:帐号+CpuId+diskId+macAdr+年月日时分秒毫秒+随机数
2.CpuId+broadId+macAdr:为客户端PC讯息,由客户端提供;
CREATE DEFINER=`root`@`localhost` PROCEDURE `drpserialnum_procedure`(in chanel varchar(19),in shop varchar(19),in token varchar(199),in userId varchar(19))
BEGIN
insert into drpserialnum(userChanel,userShop,tokens,userAcc) values (chanel,shop,token,userId);
set @shopId=null;
-- 1.order by ID desc limit 0,1为双重保护,谨防tokens出现重复值
select ID from drpserialnum where userChanel=chanel and userShop=shop and tokens=token and userAcc=userId order by ID desc limit 0,1 into @shopId;
-- 1.简易lock查询;
select count(ID) as serialNum from drpserialnum where userChanel=chanel and userShop=shop and ID<=@shopId;
END
用mysql workbench简易测试如下:
set @chanel="chanel_A";
set @shop="shop_A";
-- 此处token为临时测试数据,测试时,应尽量避免重复值
set @token="1234567890";
set @userId="18651500012";
call drpserialnum_procedure(@chanel,@shop,@token,@userId);
查询同一个部门的所有的单据记录去进行所谓的 max 计算,这就会产生幻想读错误。查询一个统一的“各部门编号表”来管理max数值,可以提高性能(根本不需要 max 统计函数),但是会产生脏读。
解决这类问题,数据库事务就是干这个事情的,是很普通的技术。除了简单地分配磁盘空间来保存数据记录和索引以外,进行数据库编程主要就是学习的原理就是事务机制、sql语言。
如果是小项目,就好像当年的12306的承包商认为国家花大价钱买贵的服务器就能解决性能问题,那么你用数据库机制来处理一般的设计问题就可以了。如果你面对的是成本压力,那么就需要更多技术,例如你可能设计一个SOA服务专门用来在内存中来统一分配流水号,这肯定就比数据库机制快1万倍速度。
SQL建立二张表:
部门表:部门ID,部门编号,部门名称。
单据表:单据ID,编号,........,部门ID
程序实现思路:
1.由用户选择部门:等选定部门后,系统记录该部门的部门ID
2.连接数据查询单据表,SELECT 编号 FROM 单据表 WHERE 部门ID=第一步记录的部门ID ORDER BY 编号 DESC
3.将此编号进行Substring,然后在序列号的部份加上1.
4.然后再格式化编号,达到你想的格式。
这样就完成了。
如果是多张表有此需求,可以写一个公用类,然后只需调用就可以了。
希望对你有所帮助。
使用一个专门用来记录唯一的 max 最终值的表,尚且会让所有的相关客户端卡住,那么这种把所有单据都锁死在事务中的方法、将所有单据查询语句(即使不是用来处理最大编号的)的事务都卡死的方法,更加是性能杀手。以关系数据库的方式,只有在事务中才能保证最大编号唯一,于是不得不一直死死卡住事务保护严密性,所以这样的系统适合个人玩儿,不适合大公司用。