最近遇到一个问题:高并发环境下,如何避免MYSQL一张表里的某些列不要重复。

同其他博友一样 https://blog.csdn.net/jacketinsysu/article/details/51526284 提出这个问题。

方式一:使用Mysql自带的列唯一索引(Unique)

可以在声明表的时候就加入这样一个约束(下面是mysql的语法):

CREATE TABLE IF NOT EXISTS `test_orderno2` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(50) NOT NULL COMMENT '名称',
`order_no` bigint unsigned NOT NULL COMMENT '编号',
`createtime` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_order_no` (`order_no`),
UNIQUE KEY `uniq_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '测试编号';
CREATE TABLE `test_orderno3` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`order_no` bigint(20) unsigned NOT NULL COMMENT '自定义编号',
`order_simple` char(21) NOT NULL COMMENT '简单编号',
`order_complex` char(30) NOT NULL COMMENT '复杂编号',
`createtime` int(10) unsigned NOT NULL DEFAULT '' COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_order_no` (`order_no`),
UNIQUE KEY `uniq_order_simple` (`order_simple`),
UNIQUE KEY `uniq_order_complex` (`order_complex`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试编号3';

这里对  test_orderno2 表设置了两个列的唯一索引,在插入数据的同时会检查该表这两列是存在,存在则会抛出sql错误

SQLSTATE[]: Integrity constraint violation: 1062 Duplicate entry '' for key 'uniq_order_no

新增行的PHP代码如下:

$count = $test_orderno2->count();

$addData['name'] = implode( '',explode('.',uniqid('',true)) );
$addData['order_no'] = sprintf( "2018%06s",++$count );
$addData['createtime'] = time(); $status = $test_orderno2->add($addData);
$test_orderno3 = M('test_orderno3');
$count = $test_orderno3->count();
$addData['order_no'] = sprintf( "2018%06s",++$count );
// 唯一性较高的唯一编号(21位)
$system_no = uniqid();
$system_no_date = date( 'YmdHis',hexdec(substr($system_no,0,8)) );
$system_no_rand = sprintf( "%07s",hexdec(substr($system_no,8,5)) );
$addData['order_simple'] = $system_no_date.$system_no_rand;
// 唯一性高的唯一编号(30位)
$system_no = implode( '',explode('.',uniqid('',true)) );
$system_no_date = date( 'YmdHis',hexdec(substr($system_no,0,8)) );
$system_no_rand = sprintf( "%07s",hexdec(substr($system_no,8,5)) );
$more_entropy = substr($system_no,13,9);
$addData['order_complex'] = $system_no_date.$system_no_rand.$more_entropy;
$addData['createtime'] = time();
// $this->ajaxReturn($addData);
$status = $test_orderno3->add($addData);
$this->ajaxReturn(array('status'=>$status));

这样在高并发的时候只满足一个客户端请求,其他客户端请求全部会抛出sql错误。

如果业务需求在高并发的时候要正常处理多个客户端请求成功,则不建议采用该方式

方式二:使用PHP代码进行唯一编号的分配

string uniqid ([ string $prefix = "" [, bool $more_entropy = false ]] )

PHP函数 uniqid 生成唯一编号代码如下:

/**
* 获取一个带前缀、基于当前时间微秒数的唯一ID。
*/
// 最简单的一种
$uniqid = uniqid(); // => string '5b11088f3c40a' (length=13)
// 添加前缀
$uniqid = uniqid('j_'); // => string 'j_5b11088f3c40a' (length=15)
// 设置combined linear congruential generator,使得唯一性更强
$uniqid = uniqid('',true); // => string '5b11094264cd58.46100058' (length=23)

了解到 uniqid 的使用,则可以根据该函数来做唯一列

// 一行代码得到唯一列
$uniqid = implode( '',explode('.',uniqid('',true)) ); // => string '5b1109c17228c598550406' (length=22)

方式三:使用PHP代码进行唯一编号的分配,并分配是数字日期型

直接上代码:

 // 1. 并发量高使用  22 (唯一性高)
$system_no = implode( '',explode('.',uniqid('',true)) );
var_dump( $system_no );
$system_no_date = date( 'YmdHis',hexdec(substr($system_no,0,8)) );
$system_no_rand = sprintf( "%07s",hexdec(substr($system_no,8,5)) );
$more_entropy = substr($system_no,13,9);
// var_dump( $system_no_date."-".$system_no_rand."-".$more_entropy );
var_dump( $system_no_date.$system_no_rand.$more_entropy );

line.2-------------得到方式二中的22位唯一字符串

line.4-------------将22中前8位取出,经过研究发现前8既然是当前时间戳16进制,所以根据公式可以得出当前时间戳的YmdHis格式

line.5-------------随后又出去8位到13位,经过研究发现这5位也是16进制,想转化成数字需要锁定FFFFF的值=1048575,最大7位,则使用%07s不足7位则前面补0保持7位

line.6-------------最后还剩下9位数字是为了增加唯一性的,则不用理会

line.8-------------30位的日期型唯一编号便出炉了

 // 2. 通常返回  13 (唯一性较高)
$system_no = uniqid();
var_dump( $system_no );
$system_no_date = date( 'YmdHis',hexdec(substr($system_no,0,8)) );
$system_no_rand = sprintf( "%07s",hexdec(substr($system_no,8,5)) );
// var_dump( $system_no_date."-".$system_no_rand );
var_dump( $system_no_date.$system_no_rand );

line.2-------------得到方式二中的13位唯一字符串

line.4-------------将22中前8位取出,经过研究发现前8既然是当前时间戳16进制,所以根据公式可以得出当前时间戳的YmdHis格式

line.5-------------随后又出去8位到13位,经过研究发现这5位也是16进制,想转化成数字需要锁定FFFFF的值=1048575,最大7位,则使用%07s不足7位则前面补0保持7位

line.7-------------21位的日期型唯一编号便出炉了

Mysql表中唯一编号的分配机制的更多相关文章

  1. php实例根据ID删除mysql表中的数据

    在动态网站开发中,我们经常要根据ID删除表中的数据,例如用户删除帖子,就需要根据ID删除帖子.本文章向大家介绍php根据ID删除表中数据的实例,需要的朋友可以参考一下本文章的实例. php实例根据ID ...

  2. 清除mysql表中数据

    delete from 表名; truncate table 表名; 不带where参数的delete语句可以删除mysql表中所有内容,使用truncate table也可以清空mysql表中所有内 ...

  3. php实例源码之获取mysql表中所有行和列

    本文章向大家介绍php获取mysql表中所有行和列的源码,主要使用到mysql_num_rows和mysql_fetch_row等php的数据库操作函数,该实例有助于大家熟悉PHP mysql数据库编 ...

  4. CSV文件插入到mysql表中指定列

    参考资料: -CSV文件插入到mysql表中指定列

  5. 如何实现MySQL表数据随机读取?从mysql表中读取随机数据

    文章转自 http://blog.efbase.org/2006/10/16/244/如何实现MySQL表数据随机读取?从mysql表中读取随机数据?以前在群里讨论过这个问题,比较的有意思.mysql ...

  6. 【MySQL】测试MySQL表中安全删除重复数据只保留一条的相关方法

    第二篇文章测试说明 开发测试中,难免会存在一些重复行数据,因此常常会造成一些测试异常. 下面简单测试mysql表删除重复数据行的相关操作. 主要通过一下三个大标题来测试说明: 02.尝试删除dept_ ...

  7. 解决在mysql表中删除自增id数据后,再添加数据时,id不会自增1的问题

    https://blog.csdn.net/shaojunbo24/article/details/50036859 问题:mysql表中删除自增id数据后,再添加数据时,id不会紧接.比如:自增id ...

  8. 如何解决前端传来的时间格式与mysql表中时间格式不匹配的查询问题

    前端传过来的时间格式为“2016-07-11 11:13:10”,而数据表中对应字段`add_time`的格式为“2016-7-11”,此时sql不能直接用 "where `add_time ...

  9. 使用kettle工具将文本文件的内容插入Linux虚拟机下的mysql表中

    一.      解压kettle包 1.把包拷到Linux系统下 还有mysql的驱动包 2.解压zip后缀的包 输入命令:unzip /software/pdi-ce-7.0.0.0-25.zip ...

随机推荐

  1. TestLink汉化操作

    实验环境版本 xampp-windows-x64-7.3.2-0-VC15-installer + testlink-1.9.19 汉化操作如下 打开testlink的配置文件F:\xampp\htd ...

  2. 36个让人惊讶的 CSS3 动画效果演示【转】

    本文收集了35个惊人的 CSS3 动画演示,它们将证明 CSS3 Transform 和 Transition 属性的强大能力.CSS 是网页设计非常重要的一部分,随着越来越多的浏览器对 CSS3 支 ...

  3. Linux --Unbuntu php项目对应不同php版本

    直入主题 因服务器上项目使用php版本有不同要求,特此解决一下. 下载 服务器上已有php7.0版本,安装7.0的方法自行百度,apt-get管理工具可直接install安装 然后安装一下需要的版本. ...

  4. python 中 打印及格式化字符串的相关方法

    原文 将值转换为字符串 Python 有多种方式将任何值转为字符串: 将它传给 repr() 或 str() 函数. repr() 和 str() 的区别,看几个例子: >>> pr ...

  5. C和C指针小记(六)-基本声明、指针声明、typedef 、常量、作用域、链接属性、存储类型、static

    1.变量的声明 声明变量的基本形式: 说明符号(一个或者多个) 声明表达式列表 说明符 (specifier) 包含一些关键字,用于描述被声明的标识符的基本类型,它也可用户改变标识符的缺省存储类型和作 ...

  6. mysql之workbench如何只导出(insert语句)数据

    https://www.jianshu.com/p/a5cd14bc5499 1. 说明: 出发点: 由于特殊原因,我们只想导出数据库中的数据(insert into语句格式的),但是在网上找到的资源 ...

  7. jquery中选取兄弟节点的方法

    $('#id').siblings() 当前元素所有的兄弟节点$('#id').prev() 当前元素前一个兄弟节点$('#id').prevaAll() 当前元素之前所有的兄弟节点$('#id'). ...

  8. panda核心数据结构

    Series Series是一维带标签的数组,数组里可以放任意的数据(整数.浮点数.字符串.python Object)等等 创建函数: (1)s = pd.Series(data,index=ind ...

  9. Java如何编写Servlet程序

    一:Servlet Servlet是Java服务器端编程,不同于一般的Java应用程序,Servlet程序是运行在服务器上的,服务器有很多种,Tomcat只是其中一种. 例子: 在Eclipse中新建 ...

  10. 洛谷P3224 永无乡 [HNOI2012] 线段树/splay/treap

    正解:线段树合并 解题报告: 传送门! 这题也是有很多解法,eg:splay,treap,... 然而我都不会我会学的QAQ! 反正今天就只讲下线段树合并怎么做QAQ 首先看到这样子的说第k重要的是什 ...