国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > MySQL > 正文

MySQL分表自增ID問題的解決方法

2024-07-24 13:09:44
字體:
供稿:網(wǎng)友

當(dāng)我們對MySQL進(jìn)行分表操作后,將不能依賴MySQL的自動(dòng)增量來產(chǎn)生唯一ID了,因?yàn)閿?shù)據(jù)已經(jīng)分散到多個(gè)表中?! ?br />  應(yīng)盡量避免使用自增IP來做為主鍵,為數(shù)據(jù)庫分表操作帶來極大的不便。
 在postgreSQL、oracle、db2數(shù)據(jù)庫中有一個(gè)特殊的特性---sequence。 任何時(shí)候數(shù)據(jù)庫可以根據(jù)當(dāng)前表中的記錄數(shù)大小和步長來獲取到該表下一條記錄數(shù)。然而,MySQL是沒有這種序列對象的。
 可以通過下面的方法來實(shí)現(xiàn)sequence特性產(chǎn)生唯一ID:

 1. 通過MySQL表生成ID
 對于插入也就是insert操作,首先就是獲取唯一的id了,就需要一個(gè)表來專門創(chuàng)建id,插入一條記錄,并獲取最后插入的ID。代碼如下: 

CREATE TABLE `ttlsa_com`.`create_id` ( `id` BIGINT( 20 ) NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE = MYISAM 

 也就是說,當(dāng)我們需要插入數(shù)據(jù)的時(shí)候,必須由這個(gè)表來產(chǎn)生id值,我的php代碼的方法如下:

<?php function get_AI_ID() {  $sql = "insert into create_id (id) values('')";  $this->db->query($sql);  return $this->db->insertID(); } ?> 

這種方法效果很好,但是在高并發(fā)情況下,MySQL的AUTO_INCREMENT將導(dǎo)致整個(gè)數(shù)據(jù)庫慢。如果存在自增字段,MySQL會(huì)維護(hù)一個(gè)自增 鎖,innodb會(huì)在內(nèi)存里保存一個(gè)計(jì)數(shù)器來記錄auto_increment值,當(dāng)插入一個(gè)新行數(shù)據(jù)時(shí),就會(huì)用一個(gè)表鎖來鎖住這個(gè)計(jì)數(shù)器,直到插入結(jié) 束。如果是一行一行的插入是沒有問題的,但是在高并發(fā)情況下,那就悲催了,表鎖會(huì)引起SQL阻塞,極大的影響性能,還可能會(huì)達(dá)到 max_connections值。
 innodb_autoinc_lock_mode:可以設(shè)定3個(gè)值:0、1、2
 0:traditonal (每次都會(huì)產(chǎn)生表鎖)
 1:consecutive (默認(rèn),可預(yù)判行數(shù)時(shí)使用新方式,不可時(shí)使用表鎖,對于simple insert會(huì)獲得批量的鎖,保證連續(xù)插入)
 2:interleaved (不會(huì)鎖表,來一個(gè)處理一個(gè),并發(fā)最高)
 對于myisam表引擎是traditional,每次都會(huì)進(jìn)行表鎖的。 

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. 隊(duì)列方式
 其實(shí)這也算是上面的一個(gè)解說
 使用隊(duì)列服務(wù),如redis、memcacheq等等,將一定量的ID預(yù)分配在一個(gè)隊(duì)列里,每次插入操作,先從隊(duì)列中獲取一個(gè)ID,若插入失敗的話,將該ID再次添加到隊(duì)列中,同時(shí)監(jiān)控隊(duì)列數(shù)量,當(dāng)小于閥值時(shí),自動(dòng)向隊(duì)列中添加元素。
 這種方式可以有規(guī)劃的對ID進(jìn)行分配,還會(huì)帶來經(jīng)濟(jì)效應(yīng),比如QQ號碼,各種靚號,明碼標(biāo)價(jià)。如網(wǎng)站的userid, 允許uid登陸,推出各種靚號,明碼標(biāo)價(jià),對于普通的ID打亂后再隨機(jī)分配。

<?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()); 

監(jiān)控隊(duì)列數(shù)量,并自動(dòng)補(bǔ)充隊(duì)列和取到id但并沒有使用

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請移步到MYSQL教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 惠来县| 河曲县| 马关县| 从化市| 山阳县| 资源县| 台前县| 龙陵县| 永安市| 陈巴尔虎旗| 高淳县| 宾阳县| 防城港市| 湖口县| 海口市| 肇庆市| 延川县| 潼南县| 鄂州市| 兴城市| 微博| 罗平县| 鄂州市| 新晃| 沽源县| 塘沽区| 古交市| 永平县| 通山县| 邓州市| 辛集市| 大余县| 梅州市| 新田县| 库车县| 德保县| 雷波县| 高淳县| 大埔县| 安远县| 新丰县|