MySQL分表自增ID成績的處理辦法。本站提示廣大學習愛好者:(MySQL分表自增ID成績的處理辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是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( 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但並沒有應用
以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。