mysql分表id维护_MySQL分表自增ID解决方案
当我们对MySQL进行分表操作后,将不能依赖MySQL的自动增量来产生唯一ID了,因为数据已经分散到多个表中。
应尽量避免使用自增IP来做为主键,为数据库分表操作带来极大的不便。
在postgreSQL、oracle、db2数据库中有一个特殊的特性---sequence。 任何时候数据库可以根据当前表中的记录数大小和步长来获取到该表下一条记录数。然而,MySQL是没有这种序列对象的。
可以通过下面的方法来实现sequence特性产生唯一ID:
1. 通过MySQL表生成ID
在《关于MySQL分表操作的研究》提到了一种方法:
对于插入也就是insert操作,首先就是获取唯一的id了,就需要一个表来专门创建id,插入一条记录,并获取最后插入的ID。代码如下:
CREATE TABLE `ttlsa_com`.`create_id` (
`id` BIGINT( 20 ) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE = MYISAM
1
2
3
CREATETABLE`ttlsa_com`.`create_id`(
`id`BIGINT(20)NOTNULLAUTO_INCREMENTPRIMARYKEY
)ENGINE=MYISAM
也就是说,当我们需要插入数据的时候,必须由这个表来产生id值,我的php代码的方法如下:
function get_AI_ID() {
$sql = "insert into create_id (id) values('')";
$this->db->query($sql);
return $this->db->insertID();
}
?>
1
2
3
4
5
6
7
functionget_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);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
functionget_next_autoincrement_waitlock($timeout=60){
$count=$timeout>0?$timeout:60;
while($r->get("serial:lock")){
$count++;
sleep(1);
if($count>10)
returnfalse;
}
returntrue;
}
functionget_next_autoincrement($timeout=60){
// first check if we are locked...
if(get_next_autoincrement_waitlock($timeout)==false)
return0;
$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.
return0;
}
$r=newRedis();
$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打乱后再随机分配。
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());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
classcommon{
private$r;
functionconstruct(){
$this->__construct();
}
publicfunction__construct(){
$this->r=newRedis();
$this->r->connect('127.0.0.1',6379);
}
functionset_queue_id($ids){
if(is_array($ids)&&isset($ids)){
foreach($idsas$id){
$this->r->LPUSH('next_autoincrement',$id);
}
}
}
functionget_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=newcommon();
$id->set_queue_id($createid);
var_dump($id->get_next_autoincrement());
监控队列数量,并自动补充队列和取到id但并没有使用,相关代码没有贴出来。
如需转载请注明出处:MySQL分表自增ID解决方案 http://www.ttlsa.com/html/2244.html
mysql分表id维护_MySQL分表自增ID解决方案相关推荐
- mysql 分表和分区_Mysql分表和分区的区别
一,什么是mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看mysql分表的3种方法 什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘 ...
- mysql 分表 条件查询_mysql分表+查询
最近面试,问到关与mysql数据库的分表一些问题,如设计一个千万级别的会员数据库,当时想到了分表,但是当问到如何跟据username查询到用户的信息时,这时,有点卡住了,所以为了让自已重新认识分表,而 ...
- mysql分表的原则_mysql分表规则(转)
author:skate time:2013/05/14 Mysql分表准则 在大量使用mysql时,数据量大.高访问时,为了提高性能需要分表处理,简介下mysql分表的标准,后续会继续补充 环境: ...
- mysql分表的原则_Mysql分表准则
Mysql分表准则 在大量使用mysql时,数据量大.高访问时,为了提高性能需要分表处理,简介下mysql分表的标准,后续会继续补充 环境: 业务类型:OLTP 硬件: cpu:8cpu 2.4GHZ ...
- mysql 分表后查询_Mysql分表后怎么查询效率高?
胸弟,mysql分表要慎之又慎,没有必要的情况下千万不要贸然分库分表.真到了非拆不可的时候,一定要结合实际业务,多花点时间做方案预研.像你们这个方案,按日期一天一张表,这完全是拍脑袋想出来的啊,给自己 ...
- mysql分表方法-----MRG_MyISAM引擎分表法
一般来说,当我们的数据库的数据超过了100w记录的时候就应该考虑分表或者分区了,这次我来详细说说分表的一些方法.目前我所知道的方法都是MYISAM的,INNODB如何做分表并且保留事务和外键,我还不是 ...
- mysql 分表 id_MySQL分表自增ID解决方案
当我们对MySQL进行分表操作后,将不能依赖MySQL的自动增量来产生唯一ID了,因为数据已经分散到多个表中. 应尽量避免使用自增ID来做为主键,为数据库分表操作带来极大的不便. 在postgreSQ ...
- Mysql系列七:分库分表技术难题之分布式全局唯一id解决方案
Mysql系列七:分库分表技术难题之分布式全局唯一id解决方案 参考文章: (1)Mysql系列七:分库分表技术难题之分布式全局唯一id解决方案 (2)https://www.cnblogs.com/ ...
- mysql分表 查询 优化_MySQL性能管理及架构(查询优化、分库分表)一遍文章搞定...
相关配置参数: slow_query_log # 启动停止记录慢查日志,慢查询日志默认是没有开启的可以在配置文件中开启(on) slow_query_log_file # 指定慢查日志的存储路径及文件 ...
最新文章
- c++ #define 预处理器
- fast-rcnn练习资料整理
- jQuery+css模拟下拉框模糊搜索的实现
- Python3 Selenium自动化web测试 == 第三节 常用WebDriver API使用示例上(24个API)
- SpringMVC-Helloworld 的归纳理解
- 掌握shell编程中数组的常见用法及示例
- 令新手头痛的java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet错误...
- 悟透JavaScript--可爱与智慧并存,灵感与诙谐共生
- FPGA智能传感系统(二)基于FPGA的交通灯设计
- 基于3D关节点的人体动作识别综述
- 测井曲线绘图显示算法总结——双缓冲技术
- 利用CDLinux里面的水滴破解路由器密码的教程
- 小爱同学app安卓版_小爱同学app2.0.1 安卓版 下载 - 51下载网
- Codeforces Round #531 (Div. 3) F.Elongated Matrix(状压dp)
- Python为什么这么多人说好?
- 【Eclipse IDEA】IDEA 导入 eclipse Web项目
- linux 下 调笔记本亮度,Linux下如何保存笔记本屏幕亮度设置(背光亮度)
- Broadcasting
- POJ3255 Roadblocks ——次短路
- 用接口实现计算每个立方体的体积并输出结果的程序(接口及多态性及匿名方法的结合使用)