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)); //随机数 ...
随机推荐
- 编写CLR存储过程中使用SqlDataRecord
温习一下这些天学习的CLR编程,存储过程,函数. 编写CLR的存储过程,运行起来的效率,果然比普通的SQL语句,存储过程或是函数均高. 以后专案需求,或是执行效率较高的SQL,得写成CLR程序,再部署 ...
- c# TCP Socket通讯基础
在做网络通讯方面的程序时,必不可少的是Socket通讯. 那么我们需要有一套既定的,简易的通讯流程. 如下: <pre name="code" class="csh ...
- C# 重载的几种实现
算法重用是非常普遍的需求,在C#中可以使用如下手段实现,非常简单,自己记录一下,方便查询. 以一个小功能为例来说明一下:打印1-5这5个数,和A-E这5个字符. 重载方式 static void Ma ...
- C#的变迁史 - C# 5.0 之并行编程总结篇
C# 5.0 搭载于.NET 4.5和VS2012之上. 同步操作既简单又方便,我们平时都用它.但是对于某些情况,使用同步代码会严重影响程序的可响应性,通常来说就是影响程序性能.这些情况下,我们通常是 ...
- 获取枚举值上的Description特性说明
/// <summary> /// 获取枚举值上的Description特性说明 /// </summary> /// <typeparam name="T&q ...
- 使用MySQL WorkBench导入数据库
1. 在MySQL WorkBench的Server Administrator中双击要连接的数据库: 2. 点击左边的Data Import/Restore; 3. Import from Dump ...
- CSS3与页面布局学习笔记(一)——概要、选择器、特殊性与刻度单位
web前端开发者最最注的内容是三个:HTML.CSS与JavaScript,他们分别在不同方面发挥自己的作用,HTML实现页面结构,CSS完成页面的表现与风格,JavaScript实现一些客户端的功能 ...
- 分享50款 Android 移动应用程序图标【下篇】
在这个移动程序流行的时代,持续增长的应用程序经济充满了商业机遇.任何对应用程序设计感兴趣的人,将会喜欢上这里的50个独特的 Android 应用程序图标.这些例子中的图标能够让应用程序的设计更具吸引力 ...
- 【zepto学习笔记02】零碎点
前言 上次我们看了zepto的选择器方面的东西,其实zepto简单很大程度是因为他用了最新的检索器querySelectorAll,今天我们来学习下zepto的一些零碎点的地方吧,主要根据zepto官 ...
- 前端js文件合并三种方式
最近在思考前端js文件该如何合并,当然不包括不能合并文件,而是我们能合并的文件,想了想应该也只有三种方式. 三个方式如下: 1. 一个大文件,所有js合并成一个大文件,所有页面都引用它. 2. 各个页 ...