MySQL分表自增ID问题的解决方法_Mysql

当我们对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( 20 ) 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 = 60){
 $count = $timeout > 0 ? $timeout : 60;

 while($r->get("serial:lock")){
 $count++;
 sleep(1);
 if ($count > 10)
 return false;
 }

 return true;
}

function get_next_autoincrement($timeout = 60){
 // first check if we are locked...
 if (get_next_autoincrement_waitlock($timeout) == false)
 return 0;

 $id = $r->incr("serial");

 if ( $id > 1 )
 return $id;

 // if ID == 1, we assume we do not have "serial" key...

 // first we need to get lock.
 if ($r->setnx("serial:lock"), 1){
 $r->expire("serial:lock", 60 * 5);

 // 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 0;
}

$r = new Redis();
$r->connect("127.0.0.1", "6379");

$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', 6379);
 }

 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)<20){
 $num=rand(1000,4000);
 if(!in_array($num,$createid))
  $createid[]=$num;
}

$id=new common();
$id->set_queue_id($createid);

var_dump($id->get_next_autoincrement());

监控队列数量,并自动补充队列和取到id但并没有使用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索MySQL分表自增ID
, MySQL分表
MySQL自增ID
mysql自增id、mysql自增id 重置、mysql获取自增id、mysql返回自增id、mysql查询自增id,以便于您获取更多的相关知识。

时间: 2024-12-02 15:01:25

MySQL分表自增ID问题的解决方法_Mysql的相关文章

mysql安装时出现各种常见问题的解决方法_Mysql

小编为大家整理许多mysql安装时出现各种常见问题的解决方法,供大家参考,具体内容如下 问题一: 当各位在安装.重装时出现could not start the service mysql error:0原因: 卸载mysql时并没有完全删除相关文件和服务,需要手动清除. 安装到最后一步execute时不能启动服务的解决方法: 首先,在管理工具->服务里面将MySQL的服务给停止(有的是没有安装成功,有这个服务,但是已经停止了的),win+R->cmd,打开命令提示符窗口,输入命令:sc de

MySql 修改密码后的错误快速解决方法_Mysql

设置好密码后,使用数据库时出现如下错误: ERROR 1820 (HY000): You must reset your password using ALTER USER statement befo re executing this statement. You must SET PASSWORD before executing this statement的解决方法 今天在MySql5.6操作时报错:You must SET PASSWORD before executing this

mysql自增ID起始值修改方法_Mysql

在mysql中很多朋友都认为字段为AUTO_INCREMENT类型自增ID值是无法修改,其实这样理解是错误的,下面介绍mysql自增ID的起始值修改与设置方法.通常的设置自增字段的方法:创建表格时添加: 复制代码 代码如下: create table table1(id int auto_increment primary key,...) 创建表格后添加: 复制代码 代码如下: alter table table1 add id int auto_increment primary key 自

mysql表物理文件被误删的解决方法_Mysql

前言       1.该方法只介绍了如何救回这个表名(数据不恢复) 如果想要恢复原来数据 直接用extundelete把文件恢复后放回去即可       2.并且是适用于平时没有全备的情况下  如果有全备 直接那全备的frm和idb文件放回去 就可以了       3.该方法同样适用于数据表迁移(只迁移一个表)  因为discard再import的速度 远比先dump再恢复的速度要快得多 建议: 平时备份一下表结构是非常重要的 -- 如果你直接删除了mysql的表文件 (.frm .idb) 

winxp 安装MYSQL 出现Error 1045 access denied 的解决方法_Mysql

操作系统:WINDOWS-XP 系统 数据库版本:mysql 5.x 提示:access denied for user 'root'@'localhost' using password yes/no 原来都好好的,今天开机上来提示上面的这个错误,重启 MySQL 还是不可以. 注意我这里的环境是 WINDOWS-XP 系统,LINUX 系统下的操作没有验证过,情况不清楚. 1. 管理员登陆系统,停止 MySQL 服务或者结束 MySQL 进程. 2. 启动 WINDOWS 的命令行窗口(即通

MYSQL无法连接 提示10055错误的解决方法_Mysql

解决方法:(以下内容为本人亲自实践原创) 总结一下,应该是连接数的问题,那么服务器上有些什么连接数: 1.IIS网站服务器中各个网站中有"连接超时时间","会话超时时间": 2.其它程序占用的服务器连接数(如SMTP服务在发信出去的时候可能有很多个连接数) 3.服务器本身的TCP/IP连接数,如xp系统就有个限制,不过server 2003系统似乎没这个限制. 解决操作: 1.我的服务器上面有几个网站,其中有个网站有个自动发信的功能,用"netstat -

MySQL 5.0.16乱码问题的解决方法_Mysql

怎样解决MySQL 5 0 16的乱码问题? 本文给出了解决方法:问:怎样解决MySQL 5.0.16的乱码问题? 答:MySQL 5.0.16的乱码问题可以用下面的方法解决:1.设置phpMyAdmin Language:Chinese simplified (zh-utf-8) MySQL 字符集:UTF-8 Unicode (utf8) MySQL 连接校对 gbk_chinese_ci2.创建数据库时 整理设置成 gbk_chinese_ci 3.用SQL建立表中 ENGINE=MyIS

MySQL server has gone away 问题的解决方法_Mysql

mysql出现ERROR : (2006, 'MySQL server has gone away') 的问题意思就是指client和MySQL server之间的链接断开了. 造成这样的原因一般是sql操作的时间过长,或者是传送的数据太大(例如使用insert ... values的语句过长, 这种情况可以通过修改max_allowed_packed的配置参数来避免,也可以在程序中将数据分批插入). 产生这个问题的原因有很多,总结下网上的分析: 原因一. MySQL 服务宕了 判断是否属于这个

MySQL服务器进程CPU占用100%的解决方法_Mysql

朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下.此主机有10个左右的 database, 分别给十个网站调用.据朋友测试,导致 mysqld-nt.exe cpu 占用奇高的是网站A,一旦在 IIS 中将此网站停止服务,CPU 占用就降下来了.一启用,则马上上升. MYSQL CPU 占用 100% 的解决过程 今天早上仔细检查了一下.目前此网站的七日平均日 IP 为