MySQL分表自增ID解决方案
当我们对MySQL进行分表操作后,将不能依赖MySQL的自动增量来产生唯一ID了,因为数据已经分散到多个表中。
应尽量避免使用自增IP来做为主键,为数据库分表操作带来极大的不便。
在postgreSQL、oracle、db2数据库中有一个特殊的特性---sequence。 任何时候数据库可以根据当前表中的记录数大小和步长来获取到该表下一条记录数。然而,MySQL是没有这种序列对象的。
可以通过下面的方法来实现sequence特性产生唯一ID:
1. 通过MySQL表生成ID
对于插入也就是insert操作,首先就是获取唯一的id了,就需要一个表来专门创建id,插入一条记录,并获取最后插入的ID。代码如下:
CREATE TABLE `ttlsa_com`.`create_id` (
`id` BIGINT( ) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE = MYISAM
也就是说,当我们需要插入数据的时候,必须由这个表来产生id值,我的php代码的方法如下:
<?php
function get_AI_ID() {
$sql = "insert into create_id (id) values('')";
$this->db->query($sql);
return $this->db->insertID();
}
?>
这种方法效果很好,但是在高并发情况下,MySQL的AUTO_INCREMENT将导致整个数据库慢。如果存在自增字段,MySQL会维护一个自增 锁,innodb会在内存里保存一个计数器来记录auto_increment值,当插入一个新行数据时,就会用一个表锁来锁住这个计数器,直到插入结 束。如果是一行一行的插入是没有问题的,但是在高并发情况下,那就悲催了,表锁会引起SQL阻塞,极大的影响性能,还可能会达到 max_connections值。
innodb_autoinc_lock_mode:可以设定3个值:0、1、2
0:traditonal (每次都会产生表锁)
1:consecutive (默认,可预判行数时使用新方式,不可时使用表锁,对于simple insert会获得批量的锁,保证连续插入)
2:interleaved (不会锁表,来一个处理一个,并发最高)
对于myisam表引擎是traditional,每次都会进行表锁的。
2. 通过redis生成ID
function get_next_autoincrement_waitlock($timeout = ){
$count = $timeout > ? $timeout : ;
while($r->get("serial:lock")){
$count++;
sleep();
if ($count > )
return false;
}
return true;
}
function get_next_autoincrement($timeout = ){
// first check if we are locked...
if (get_next_autoincrement_waitlock($timeout) == false)
return ;
$id = $r->incr("serial");
if ( $id > )
return $id;
// if ID == 1, we assume we do not have "serial" key...
// first we need to get lock.
if ($r->setnx("serial:lock"), ){
$r->expire("serial:lock", * );
// get max(id) from database.
$id = select_db_query("select max(id) from user_posts");
// or alternatively:
// select id from user_posts order by id desc limit 1
// increase it
$id++;
// update Redis key
$r->set("serial", $id);
// release the lock
$r->del("serial:lock");
return $id;
}
// can not get lock.
return ;
}
$r = new Redis();
$r->connect("127.0.0.1", "");
$id = get_next_autoincrement();
if ($id){
$sql = "insert into user_posts(id,user,message)values($id,'$user','$message')"
$data = exec_db_query($sql);
}
3. 队列方式
其实这也算是上面的一个解说
使用队列服务,如redis、memcacheq等等,将一定量的ID预分配在一个队列里,每次插入操作,先从队列中获取一个ID,若插入失败的话,将该ID再次添加到队列中,同时监控队列数量,当小于阀值时,自动向队列中添加元素。
这种方式可以有规划的对ID进行分配,还会带来经济效应,比如QQ号码,各种靓号,明码标价。如网站的userid, 允许uid登陆,推出各种靓号,明码标价,对于普通的ID打乱后再随机分配。
<?php
class common {
private $r;
function construct() {
$this->__construct();
}
public function __construct(){
$this->r=new Redis();
$this->r->connect('127.0.0.1', );
}
function set_queue_id($ids){
if(is_array($ids) && isset($ids)){
foreach ($ids as $id){
$this->r->LPUSH('next_autoincrement',$id);
}
}
}
function get_next_autoincrement(){
return $this->r->LPOP('next_autoincrement');
}
}
$createid=array();
while(count($createid)<){
$num=rand(,);
if(!in_array($num,$createid))
$createid[]=$num;
}
$id=new common();
$id->set_queue_id($createid);
var_dump($id->get_next_autoincrement());
监控队列数量,并自动补充队列和取到id但并没有使用
4. redis和db结合。
使用redis直接操作内存,可能性能会好些。但是如果redis死掉后,如何处理呢?把两种结合一下稳定性会更好
function next_id($name){
try{
return $this->next_id_redis($name);
}
catch(Exception $e){
return $this->next_id_db($name);
}
}
MySQL分表自增ID解决方案的更多相关文章
- MySQL分表自增ID解决方案(转)
当我们对MySQL进行分表操作后,将不能依赖MySQL的自动增量来产生唯一ID了,因为数据已经分散到多个表中. 应尽量避免使用自增IP来做为主键,为数据库分表操作带来极大的不便. 在postgreSQ ...
- mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0
mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0 #将数据库表自增ID批量清零 SELECT CONCAT( 'ALTER TABLE ', TABLE_NAME, ' AUT ...
- 数据库分表自增ID问题
.................................................................................................... ...
- mysql 数据库自增id 的总结
有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ...
- MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)
测试缘由 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了拿 ...
- MYSQL获取自增ID的四种方法
MYSQL获取自增ID的四种方法 1. select max(id) from tablename 2.SELECT LAST_INSERT_ID() 函数 LAST_INSERT_ID 是与tabl ...
- mysql数据库自增id重新从1排序的两种方法
mysql默认自增ID是从1开始了,但当我们如果有插入表或使用delete删除id之后ID就会不会从1开始了哦. 使用mysql时,通常表中会有一个自增的id字段,但当我们想将表中的数据清空重新添 ...
- DBS-MySQL:MYSQL获取自增ID的四种方法
ylbtech-DBS-MySQL:MYSQL获取自增ID的四种方法 1.返回顶部 1. 1. select max(id) from tablename 2.SELECT LAST_INSERT_I ...
- mysql 返回自增id
String dateNow= DateTime.Now.ToString("yyyyMMddhhmmss"+ new Random().Next(1, 99)); //随机数 ...
随机推荐
- Bootstrap学习笔记系列3-------Bootstrap简单表单显示
表单布局 垂直或基本表单 基本的表单结构时BootStrap自带的,创建基本表单的步骤如下: 向父<form>元素添加role = "form": 为了获取最佳的间距, ...
- jquery基本选择器id
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- sql传入组合字符串批量操作
批量操作时我们可以传入一个有规律的ID或则是其他唯一值字段的组合字符串,然后:select/update/inset......where 字段 in(传入的组合字符串),而且很多时候我们还涉及到其 ...
- No.015:3Sum
问题: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?Find all ...
- 【FOL】第三周
这周还是在改自己的这个框架,被多线程折腾了两天,最终无奈放弃在游戏启动时调用引擎进行图片相关资源的初始化,当然进展还是不错的. 嗯,下面还是以流水的方式继续记录一下本周完成的工作: 1.调通了客户端与 ...
- 性能测试学习之三—— PV->TPS转换模型&TPS波动模型
PV->TPS转换模型 由上一篇“性能测试学习之二 ——性能测试模型(PV计算模型)“ 得知 TPS = ( (80%*总PV)/(24*60*60*(T/24)))/服务器数量 转换需要注意: ...
- .Net中的并行编程-6.常用优化策略
本文是.Net中的并行编程第六篇,今天就介绍一些我在实际项目中的一些常用优化策略. 一.避免线程之间共享数据 避免线程之间共享数据主要是因为锁的问题,无论什么粒度的锁 ...
- ASP.Net之数据绑定
---恢复内容开始--- [概述]数据绑定是指从数据源获取数据或向数据源写入数据.简单的数据绑定可以是对变量或属性的绑定,比较复杂的是对ASP.NET数据绑定控件的操作 1.简单的属性绑定 基于属性的 ...
- 用node-webkit把web应用打包成桌面应用
node-webkit是一个Chromium和node.js上的结合体,通过它我们可以把建立在chrome浏览器和node.js上的web应用打包成桌面应用,而且还可以跨平台的哦.很显然比起传统的桌面 ...
- Ajax原生写法
用太久JQuery了,别忘了Ajax原生是怎么写的 var Ajax = { get : function (url, callback) { var req = Ajax.getRequest(ca ...