基于Mysql的Sequence实现方法

团队更换新框架。新的业务全部使用新的框架,甚至是新的数据库--Mysql。

这边之前一直是使用oracle,各种订单号、流水号、批次号啥的,都是直接使用oracle的sequence提供的数字序列号。现在数据库更换成Mysql了,显然以前的老方法不能适用了。

需要新写一个:

•分布式场景使用

•满足一定的并发要求

找了一些相关的资料,发现mysql这方面的实现,原理都是一条数据库记录,不断update它的值。然后大部分的实现方案,都用到了函数。

贴一下网上的代码:

基于mysql函数实现

表结构

CREATE TABLE `t_sequence` (
`sequence_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '序列名称' ,
`value` int(11) NULL DEFAULT NULL COMMENT '当前值' ,
PRIMARY KEY (`sequence_name`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
ROW_FORMAT=COMPACT
;

获取下一个值

CREATE DEFINER = `root`@`localhost` FUNCTION `nextval`(sequence_name varchar(64))
 RETURNS int(11)
BEGIN
 declare current integer;
 set current = 0;

 update t_sequence t set t.value = t.value + 1 where t.sequence_name = sequence_name;
 select t.value into current from t_sequence t where t.sequence_name = sequence_name;

 return current;
end;

并发场景有可能会出问题,虽然可以在业务层加锁,但分布式场景就无法保证了,然后效率应该也不会高。

自己实现一个,java版

原理:

•读取一条记录,缓存一个数据段,如:0-100,将记录的当前值从0修改为100

•数据库乐观锁更新,允许重试

•读取数据从缓存中读取,用完再读取数据库

不废话,上代码:

基于java实现

表结构

每次update,都是将SEQ_VALUE设置为SEQ_VALUE+STEP

CREATE TABLE `t_pub_sequence` (
 `SEQ_NAME` varchar(128) CHARACTER SET utf8 NOT NULL COMMENT '序列名称',
 `SEQ_VALUE` bigint(20) NOT NULL COMMENT '目前序列值',
 `MIN_VALUE` bigint(20) NOT NULL COMMENT '最小值',
 `MAX_VALUE` bigint(20) NOT NULL COMMENT '最大值',
 `STEP` bigint(20) NOT NULL COMMENT '每次取值的数量',
 `TM_CREATE` datetime NOT NULL COMMENT '创建时间',
 `TM_SMP` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
 PRIMARY KEY (`SEQ_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流水号生成表';

sequence接口

/**
 * <p></p>
 * @author coderzl
 * @Title MysqlSequence
 * @Description 基于mysql数据库实现的序列
 * @date 2017/6/6 23:03
 */
public interface MysqlSequence {
 /**
  * <p>
  * 获取指定sequence的序列号
  * </p>
  * @param seqName sequence名
  * @return String 序列号
  */
 public String nextVal(String seqName);
}

序列区间

用于本地缓存一段序列,从min到max区间

/**
 * <p></p>
 *
 * @author coderzl
 * @Title SequenceRange
 * @Description 序列区间,用于缓存序列
 * @date 2017/6/6 22:58
 */
 @Data
public class SequenceRange {
 private final long  min;
 private final long  max;
 /** */
 private final AtomicLong value;
 /** 是否超限 */
 private volatile boolean over = false;

 /**
  * 构造.
  *
  * @param min
  * @param max
  */
 public SequenceRange(long min, long max) {
  this.min = min;
  this.max = max;
  this.value = new AtomicLong(min);
 }

 /**
  * <p>Gets and increment</p>
  *
  * @return
  */
 public long getAndIncrement() {
  long currentValue = value.getAndIncrement();
  if (currentValue > max) {
   over = true;
   return -1;
  }

  return currentValue;
 }

} 

BO

对应数据库记录

@Data
public class MysqlSequenceBo {
 /**
  * seq名
  */
 private String seqName;
 /**
  * 当前值
  */
 private Long seqValue;
 /**
  * 最小值
  */
 private Long minValue;
 /**
  * 最大值
  */
 private Long maxValue;
 /**
  * 每次取值的数量
  */
 private Long step;
 /** */
 private Date tmCreate;
 /** */
 private Date tmSmp;

 public boolean validate(){
  //一些简单的校验。如当前值必须在最大最小值之间。step值不能大于max与min的差
  if (StringUtil.isBlank(seqName) || minValue < 0 || maxValue <= 0 || step <= 0 || minValue >= maxValue || maxValue - minValue <= step ||seqValue < minValue || seqValue > maxValue ) {
   return false;
  }
  return true;
 }
}

DAO

增删改查,其实就用到了改和查

public interface MysqlSequenceDAO {
 /**
 *
 */
 public int createSequence(MysqlSequenceBo bo);

 public int updSequence(@Param("seqName") String seqName, @Param("oldValue") long oldValue ,@Param("newValue") long newValue);

 public int delSequence(@Param("seqName") String seqName);

 public MysqlSequenceBo getSequence(@Param("seqName") String seqName);

 public List<MysqlSequenceBo> getAll();
}

Mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.xxxxx.core.sequence.impl.dao.MysqlSequenceDAO" >
 <resultMap id="BaseResultMap" type="com.xxxxx.core.sequence.impl.MysqlSequenceBo" >
  <result column="SEQ_NAME" property="seqName" jdbcType="VARCHAR" />
  <result column="SEQ_VALUE" property="seqValue" jdbcType="BIGINT" />
  <result column="MIN_VALUE" property="minValue" jdbcType="BIGINT" />
  <result column="MAX_VALUE" property="maxValue" jdbcType="BIGINT" />
  <result column="STEP" property="step" jdbcType="BIGINT" />
  <result column="TM_CREATE" property="tmCreate" jdbcType="TIMESTAMP" />
  <result column="TM_SMP" property="tmSmp" jdbcType="TIMESTAMP" />
 </resultMap>
 <delete id="delSequence" parameterType="java.lang.String" >
  delete from t_pub_sequence
  where SEQ_NAME = #{seqName,jdbcType=VARCHAR}
 </delete>
 <insert id="createSequence" parameterType="com.xxxxx.core.sequence.impl.MysqlSequenceBo" >
  insert into t_pub_sequence (SEQ_NAME,SEQ_VALUE,MIN_VALUE,MAX_VALUE,STEP,TM_CREATE)
  values (#{seqName,jdbcType=VARCHAR}, #{seqValue,jdbcType=BIGINT},
  #{minValue,jdbcType=BIGINT}, #{maxValue,jdbcType=BIGINT}, #{step,jdbcType=BIGINT},
  now())
 </insert>
 <update id="updSequence" parameterType="com.xxxxx.core.sequence.impl.MysqlSequenceBo" >
  update t_pub_sequence
  set SEQ_VALUE = #{newValue,jdbcType=BIGINT}
  where SEQ_NAME = #{seqName,jdbcType=VARCHAR} and SEQ_VALUE = #{oldValue,jdbcType=BIGINT}
 </update>

 <select id="getAll" resultMap="BaseResultMap" >
  select SEQ_NAME, SEQ_VALUE, MIN_VALUE, MAX_VALUE, STEP
  from t_pub_sequence
 </select>

 <select id="getSequence" resultMap="BaseResultMap" >
  select SEQ_NAME, SEQ_VALUE, MIN_VALUE, MAX_VALUE, STEP
  from t_pub_sequence
  where SEQ_NAME = #{seqName,jdbcType=VARCHAR}
 </select>
</mapper>

接口实现

@Repository("mysqlSequence")
public class MysqlSequenceImpl implements MysqlSequence{

 @Autowired
 private MysqlSequenceFactory mysqlSequenceFactory;
 /**
  * <p>
  * 获取指定sequence的序列号
  * </p>
  *
  * @param seqName sequence名
  * @return String 序列号
  * @author coderzl
  */
 @Override
 public String nextVal(String seqName) {
  return Objects.toString(mysqlSequenceFactory.getNextVal(seqName));
 }
}

工厂

工厂只做了两件事

•服务启动的时候,初始化数据库中所有sequence【完成序列区间缓存】

•获取sequence的下一个值

@Component
public class MysqlSequenceFactory {

 private final Lock lock = new ReentrantLock();

 /** */
 private Map<String,MysqlSequenceHolder> holderMap = new ConcurrentHashMap<>();

 @Autowired
 private MysqlSequenceDAO msqlSequenceDAO;
 /** 单个sequence初始化乐观锁更新失败重试次数 */
 @Value("${seq.init.retry:5}")
 private int initRetryNum;
 /** 单个sequence更新序列区间乐观锁更新失败重试次数 */
 @Value("${seq.get.retry:20}")
 private int getRetryNum;

 @PostConstruct
 private void init(){
  //初始化所有sequence
  initAll();
 }

 /**
  * <p> 加载表中所有sequence,完成初始化 </p>
  * @return void
  * @author coderzl
  */
 private void initAll(){
  try {
   lock.lock();
   List<MysqlSequenceBo> boList = msqlSequenceDAO.getAll();
   if (boList == null) {
    throw new IllegalArgumentException("The sequenceRecord is null!");
   }
   for (MysqlSequenceBo bo : boList) {
    MysqlSequenceHolder holder = new MysqlSequenceHolder(msqlSequenceDAO, bo,initRetryNum,getRetryNum);
    holder.init();
    holderMap.put(bo.getSeqName(), holder);
   }
  }finally {
   lock.unlock();
  }
 }

 /**
  * <p> </p>
  * @param seqName
  * @return long
  * @author coderzl
  */
 public long getNextVal(String seqName){
  MysqlSequenceHolder holder = holderMap.get(seqName);
  if (holder == null) {
   try {
    lock.lock();
    holder = holderMap.get(seqName);
    if (holder != null){
     return holder.getNextVal();
    }
    MysqlSequenceBo bo = msqlSequenceDAO.getSequence(seqName);
    holder = new MysqlSequenceHolder(msqlSequenceDAO, bo,initRetryNum,getRetryNum);
    holder.init();
    holderMap.put(seqName, holder);
   }finally {
    lock.unlock();
   }
  }
  return holder.getNextVal();
 }

}

单一sequence的Holder

•init() 初始化 其中包括参数校验,数据库记录更新,创建序列区间

•getNextVal() 获取下一个值

public class MysqlSequenceHolder {

 private final Lock lock    = new ReentrantLock();

 /** seqName */
 private String seqName;

 /** sequenceDao */
 private MysqlSequenceDAO sequenceDAO;

 private MysqlSequenceBo sequenceBo;
 /** */
 private SequenceRange sequenceRange;
 /** 是否初始化 */
 private volatile boolean  isInitialize  = false;
 /** sequence初始化重试次数 */
 private int initRetryNum;
 /** sequence获取重试次数 */
 private int getRetryNum;

 /**
  * <p> 构造方法 </p>
  * @Title MysqlSequenceHolder
  * @param sequenceDAO
  * @param sequenceBo
  * @param initRetryNum 初始化时,数据库更新失败后重试次数
  * @param getRetryNum 获取nextVal时,数据库更新失败后重试次数
  * @return
  * @author coderzl
  */
 public MysqlSequenceHolder(MysqlSequenceDAO sequenceDAO, MysqlSequenceBo sequenceBo,int initRetryNum,int getRetryNum) {
  this.sequenceDAO = sequenceDAO;
  this.sequenceBo = sequenceBo;
  this.initRetryNum = initRetryNum;
  this.getRetryNum = getRetryNum;
  if(sequenceBo != null)
   this.seqName = sequenceBo.getSeqName();
 }

 /**
  * <p> 初始化 </p>
  * @Title init
  * @param
  * @return void
  * @author coderzl
  */
 public void init(){
  if (isInitialize == true) {
   throw new SequenceException("[" + seqName + "] the MysqlSequenceHolder has inited");
  }
  if (sequenceDAO == null) {
   throw new SequenceException("[" + seqName + "] the sequenceDao is null");
  }
  if (seqName == null || seqName.trim().length() == 0) {
   throw new SequenceException("[" + seqName + "] the sequenceName is null");
  }
  if (sequenceBo == null) {
   throw new SequenceException("[" + seqName + "] the sequenceBo is null");
  }
  if (!sequenceBo.validate()){
   throw new SequenceException("[" + seqName + "] the sequenceBo validate fail. BO:"+sequenceBo);
  }
  // 初始化该sequence
  try {
   initSequenceRecord(sequenceBo);
  } catch (SequenceException e) {
   throw e;
  }
  isInitialize = true;
 }

 /**
  * <p> 获取下一个序列号 </p>
  * @Title getNextVal
  * @param
  * @return long
  * @author coderzl
  */
 public long getNextVal(){
  if(isInitialize == false){
   throw new SequenceException("[" + seqName + "] the MysqlSequenceHolder not inited");
  }
  if(sequenceRange == null){
   throw new SequenceException("[" + seqName + "] the sequenceRange is null");
  }
  long curValue = sequenceRange.getAndIncrement();

  if(curValue == -1){
   try{
    lock.lock();
    curValue = sequenceRange.getAndIncrement();
    if(curValue != -1){
     return curValue;
    }
    sequenceRange = retryRange();
    curValue = sequenceRange.getAndIncrement();
   }finally {
    lock.unlock();
   }
  }
  return curValue;
 }

 /**
  * <p> 初始化当前这条记录 </p>
  * @Title initSequenceRecord
  * @Description
  * @param sequenceBo
  * @return void
  * @author coderzl
  */
 private void initSequenceRecord(MysqlSequenceBo sequenceBo){
  //在限定次数内,乐观锁更新数据库记录
  for(int i = 1; i < initRetryNum; i++){
   //查询bo
   MysqlSequenceBo curBo = sequenceDAO.getSequence(sequenceBo.getSeqName());
   if(curBo == null){
    throw new SequenceException("[" + seqName + "] the current sequenceBo is null");
   }
   if (!curBo.validate()){
    throw new SequenceException("[" + seqName + "] the current sequenceBo validate fail");
   }
   //改变当前值
   long newValue = curBo.getSeqValue()+curBo.getStep();
   //检查当前值
   if(!checkCurrentValue(newValue,curBo)){
    newValue = resetCurrentValue(curBo);
   }
   int result = sequenceDAO.updSequence(sequenceBo.getSeqName(),curBo.getSeqValue(),newValue);
   if(result > 0){
    sequenceRange = new SequenceRange(curBo.getSeqValue(),newValue - 1);
    curBo.setSeqValue(newValue);
    this.sequenceBo = curBo;
    return;
   }else{
    continue;
   }
  }
  //限定次数内,更新失败,抛出异常
  throw new SequenceException("[" + seqName + "] sequenceBo update error");
 }

 /**
  * <p> 检查新值是否合法 新的当前值是否在最大最小值之间</p>
  * @param curValue
  * @param curBo
  * @return boolean
  * @author coderzl
  */
 private boolean checkCurrentValue(long curValue,MysqlSequenceBo curBo){
  if(curValue > curBo.getMinValue() && curValue <= curBo.getMaxValue()){
   return true;
  }
  return false;
 }

 /**
  * <p> 重置sequence当前值 :当前sequence达到最大值时,重新从最小值开始 </p>
  * @Title resetCurrentValue
  * @param curBo
  * @return long
  * @author coderzl
  */
 private long resetCurrentValue(MysqlSequenceBo curBo){
  return curBo.getMinValue();
 }

 /**
  * <p> 缓存区间使用完毕时,重新读取数据库记录,缓存新序列段 </p>
  * @Title retryRange
  * @param SequenceRange
  * @author coderzl
  */
 private SequenceRange retryRange(){
  for(int i = 1; i < getRetryNum; i++){
   //查询bo
   MysqlSequenceBo curBo = sequenceDAO.getSequence(sequenceBo.getSeqName());
   if(curBo == null){
    throw new SequenceException("[" + seqName + "] the current sequenceBo is null");
   }
   if (!curBo.validate()){
    throw new SequenceException("[" + seqName + "] the current sequenceBo validate fail");
   }
   //改变当前值
   long newValue = curBo.getSeqValue()+curBo.getStep();
   //检查当前值
   if(!checkCurrentValue(newValue,curBo)){
    newValue = resetCurrentValue(curBo);
   }
   int result = sequenceDAO.updSequence(sequenceBo.getSeqName(),curBo.getSeqValue(),newValue);
   if(result > 0){
    sequenceRange = new SequenceRange(curBo.getSeqValue(),newValue - 1);
    curBo.setSeqValue(newValue);
    this.sequenceBo = curBo;
    return sequenceRange;
   }else{
    continue;
   }
  }
  throw new SequenceException("[" + seqName + "] sequenceBo update error");

 }
}

总结

•当服务重启或异常的时候,会丢失当前服务所缓存且未用完的序列

•分布式场景,多个服务同时初始化,或者重新获取sequence时,乐观锁会保证彼此不冲突。A服务获取0-99,B服务会获取100-199,以此类推

•当该sequence获取较为频繁时,增大step值,能提升性能。但同时服务异常时,损失的序列也较多

•修改数据库里sequence的一些属性值,比如step,max等,再下一次从数据库获取时,会启用新的参数

•sequence只是提供了有限个序列号(最多max-min个),达到max后,会循环从头开始。

•由于sequence会循环,所以达到max后,再获取,就不会唯一。建议使用sequence来做业务流水号时,拼接时间。如:20170612235101+序列号

业务id拼接方法

@Service
public class JrnGeneratorService {
 private static final String SEQ_NAME = "T_SEQ_TEST";

 /** sequence服务 */
 @Autowired
 private MySqlSequence mySqlSequence;

 public String generateJrn() {
  try {
   String sequence = mySqlSequence.getNextValue(SEQ_NAME);
   sequence = leftPadding(sequence,8);
   Calendar calendar = Calendar.getInstance();
   SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
   String nowdate = sDateFormat.format(calendar.getTime());
   nowdate.substring(4, nowdate.length());
   String jrn = nowdate + sequence + RandomUtil.getFixedLengthRandom(6);//10位时间+8位序列 + 6位随机数=24位流水号
   return jrn;
  } catch (Exception e) {
   //TODO
  }
 }

 private String leftPadding(String seq,int len){
  String res ="";
  String str ="";
  if(seq.length()<len){
   for(int i=0;i<len-seq.length();i++){
    str +="0";
   }
  }
  res =str+seq;
  return res;

 }

}

以上这篇基于Mysql的Sequence实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • linux实现mysql数据库每天自动备份定时备份

     概述 备份是容灾的基础,是指为防止系统出现操作失误或系统故障导致数据丢失,而将全部或部分数据集合从应用主机的硬盘或阵列复制到其它的存储介质的过程.而对于一些网站.系统来说,数据库就是一切,所以做好数据库的备份是至关重要的! 备份是什么? 为什么要备份 容灾方案建设 存储介质 光盘 磁带 硬盘 磁盘阵列 DAS:直接附加存储 NAS:网络附加存储 SAN:存储区域网络 云存储 这里主要以本地磁盘为存储介质讲一下计划任务的添加使用,基本的备份脚本,其它存储介质只是介质的访问方式可能不大一样. 1.

  • MySQL 5.7双主同步部分表的实现过程详解

    前言 最近遇到一个需求,由于公司自身业务,两个数据库之间某些表需要实时双向同步数据,且其中任何一台数据库宕机都不会影响另外一台数据库,这里记录一下自己的技术调研,以便后期重构中使用.下面话不多说了,来一起看看详细的介绍吧. 安装MySQL5.7 推荐直接进官网 https://dev.mysql.com 下载yum源的方式安装,毕竟安全又省事. wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm y

  • 利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解

    PHP访问MySql数据库 <?php //造连接对象 $db = new MySQLi("localhost","root","","0710_test"); //写SQL语句 $sql = "select * from student"; //检测连接数据库是否成功,失败返回"连接失败",并退出程序 if(mysqli_connect_error()){ die("连

  • MySQL curdate()函数的实例详解

    MySQL CURDATE功能介绍 如果在数字上下文中使用字符串上下文或YYYMMDD格式,CURDATE()函数将以"YYYY-MM-DD"格式的值返回当前日期. 以下示例显示了如何在字符串上下文中使用CURDATE()函数. sql> SELECT CURDATE(); +------------+ | CURDATE() | +------------+ | 2017-08-10 | +------------+ 1 row in set (0.00 sec) 以下示例说明

  • 在Mac OS X中配置Apache+PHP+MySQL运行环境的详细步骤

    这是一篇超级详细的配置mac os下面php+mysql+apache的文章.非常详细 我的大部分配置就是参考上面的内容的,比如,PHP不能连接数据库,就是改一下默认的php.ini中pdo_mysql.default_socket[因为现在都用PDO了嘛.不用mysql的连接库了] 因为我是用navicat的,所以对phpmyadmin那一块的配置就不太关心了.不过MCrypt的安装可以参考. Mac OS X 内置了Apache 和 PHP,这样使用起来非常方便.本文以Mac OS X 10

  • MySQL5.7免安装版配置图文教程

    Mysql是一个比较流行且很好用的一款数据库软件,如下记录了我学习总结的mysql免安装版的配置经验. 一. 软件下载 5.7 32位https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-win32.zip 5.7 64位https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip 本次教程采用的是64位版本,诸君可根据自己电脑系统和个人喜好酌情处理. 二

  • windows下python之mysqldb模块安装方法

    之所以会写下这篇日志,是因为安装的过程有点虐心.目前这篇文章是针对windows操作系统上的mysqldb的安装.安装python的mysqldb模块,首先当然是找一些官方的网站去下载:https://pypi.python.org/pypi/MySQL-python.下载后,cmd进入MySQL-python-1.2.3文件夹,按常规的执行python setup.py install 命令安装此模块,然后就报错了: 这个报错很明显,print 进行python前,应该先确定当前mysqldb

  • oracle、mysql数据库停止与启动的批处理文件

    1.关机,取消关机 ::关机 echo 30秒之后关机 %systemroot%\system32\shutdown -s -t 30 ::取消关机 echo 取消关机 %systemroot%\system32\shutdown -a 2.oralce,或者mysql滴服务启动与关闭 ::oralce service start net start OracleVssWriterORCL net start OracleDBConsoleorcl net start OracleOraDb10

  • 基于Mysql的Sequence实现方法

    团队更换新框架.新的业务全部使用新的框架,甚至是新的数据库--Mysql. 这边之前一直是使用oracle,各种订单号.流水号.批次号啥的,都是直接使用oracle的sequence提供的数字序列号.现在数据库更换成Mysql了,显然以前的老方法不能适用了. 需要新写一个: •分布式场景使用 •满足一定的并发要求 找了一些相关的资料,发现mysql这方面的实现,原理都是一条数据库记录,不断update它的值.然后大部分的实现方案,都用到了函数. 贴一下网上的代码: 基于mysql函数实现 表结构

  • PHP基于MySQL数据库实现对象持久层的方法

    本文实例讲述了PHP基于MySQL数据库实现对象持久层的方法.分享给大家供大家参考.具体如下: 心血来潮,做了一下PHP的对象到数据库的简单持久层. 不常用PHP,对PHP也不熟,关于PHP反射的大部分内容都是现学的. 目前功能比较弱,只是完成一些简单的工作,对象之间的关系还没法映射,并且对象的成员只能支持string或者integer两种类型的. 成员变量的值也没有转义一下... 下面就贴一下代码: 首先是数据库的相关定义,该文件定义了数据库的连接属性: <?php /* * Filename

  • MySQL如何设置自动增长序列SEQUENCE的方法

    目录 1.创建表emp_seq,用来存放sequence值: 2.手动插入数据: 3.定义函数 nextval: 4.恢复默认的语句结束符: 6.执行外部SQL脚本命令 7.成功导入sql脚本后,那咱们就需要验证一下,进入mysql,并进入数据库,我这里是jsd170101 8.下面说说如何应用在DML语句中 本文主要介绍了MySQL如何设置自动增长序列 SEQUENCE,具体如下: 解决思路:由于mysql不带sequence,所以要手写的,创建一张储存sequence的表(emp_seq),

  • 基于MySql的扩展功能生成全局ID

    本文利用 MySQL的扩展功能 REPLACE INTO 来生成全局id,REPLACE INTO和INSERT的功能一样,但是当使用REPLACE INTO插入新数据行时,如果新插入的行的主键或唯一键(UNIQUE Key)已有的行重复时,已有的行会先被删除,然后再将新数据行插入(REPLACE INTO 是原始操作). 建立类似下面的表: CREATE TABLE `tickets64` ( `id` bigint(20) unsigned NOT NULL auto_increment,

  • PHP基于IMAP收取邮件的方法示例

    本文实例讲述了PHP基于IMAP收取邮件的方法.分享给大家供大家参考,具体如下: 因需要处理公司企业邮箱被退信邮件问题:刚开始的思路是通过模拟登陆,对邮件进行抓取,(这种事情对我来说,做过了很多次,轻车熟路),不过邮箱还是有点复杂的, 后来想起做邮件发送时有用到smtp来发送邮件,记得也可以收取邮件,在腾讯企业邮箱帮助http://service.exmail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1000584 看到IMAP和P

  • PHP基于XMLWriter操作xml的方法分析

    本文实例讲述了PHP基于XMLWriter操作xml的方法.分享给大家供大家参考,具体如下: 接着昨天的这次再来学习一种读写xml的方式,这种方式主要围绕XMLWriter和XMLReader进行.前者用于生成xml,后者则是用来读取并解析xml.废话不多说一起来看看吧 1. 生成xml文件或字符串 <?php header("Content-type: text/html; charset=utf-8"); $xml=new XMLWriter(); //$xml->op

  • Mysql全局ID生成方法

    生产系统随着业务增长总会经历一个业务量由小变大的过程,可扩展性是考量数据库系统高可用性的一个重要指标;在单表/数据库数据量过大,更新量不断飙涨时,MySQL DBA往往会对业务系统提出sharding的方案.既然要sharding,那么不可避免的要讨论到sharding key问题,在有些业务系统中,必须保证sharding key全局唯一,比如存放商品的数据库等,那么如何生成全局唯一的ID呢,下文将从DBA的角度介绍几种常见的方案. 1.使用CAS思想 什么是CAS协议 Memcached于1

  • PHP基于GD库的图像处理方法小结

    本文实例讲述了PHP基于GD库的图像处理方法.分享给大家供大家参考,具体如下: gd图像处理技术 extension=php_gd2.dll 创建画布 画布,一种资源型数据,可操作的图像资源 创建画布(新建) imageCreate(width,height) //创建基于调色板的画布 imageCreateTrueColor(width,height) //创建真彩色的画布 基于图片创建画布(打开) imageCreateFromJPEG( url) imageCreateFromPNG(ur

  • Spring与Mybatis基于注解整合Redis的方法

    基于这段时间折腾redis遇到了各种问题,想着整理一下.本文主要介绍基于Spring+Mybatis以注解的形式整合Redis.废话少说,进入正题. 首先准备Redis,我下的是Windows版,下载后直接启动redis-server就行了,见下图: 一,先上jar包 二,创建实体类 package com.sl.user.vo; import java.io.Serializable; import com.fasterxml.jackson.databind.PropertyNamingSt

  • Node.js使用MySQL连接池的方法实例

    本文实例讲述了Node.js使用MySQL连接池的方法.分享给大家供大家参考,具体如下: Nodejs如何使用MySQL Nodejs要连接MySQL,可以使用Nodejs的MysQL驱动来实现.比如,我们这里使用"node-mysql"连接数据库.我们使用下面的方式来连接数据库: 首先,我们需要使用nodejs的包管理工具(npm)安装mysql的驱动.命令行如下: npm install musql 现在,要在js文件中使用mysql,添加下面的代码到你的文件中: var mysq

随机推荐