MySQL分表自增ID解決方案

来源:http://www.cnblogs.com/zhenghongxin/archive/2016/06/12/5572193.html
-Advertisement-
Play Games

當我們對MySQL進行分表操作後,將不能依賴MySQL的自動增量來產生唯一ID了,因為數據已經分散到多個表中。 應儘量避免使用自增IP來做為主鍵,為資料庫分表操作帶來極大的不便。 在postgreSQL、oracle、db2資料庫中有一個特殊的特性 sequence。 任何時候資料庫可以根據當前表中 ...


當我們對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但並沒有使用

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • CSS 有兩個說不上常用的偽類 :before 和 :after,偶爾會被人用來添加些自定義格式什麼的,但是它們的功用不僅於此。前幾天發現了 Creative Link Effects 這個非常有意思的介紹創意鏈接特效的頁面,裡面驚人的效果大量使用到的特性除了 transform 屬性進行變形之外, ...
  • 在使用UeEditor中遇到幾個個坑 1.添加的html代碼中使用的樣式class被guolv掉 解決方案:在ueditor.config.js中,xss過濾白名單中,每個元素添加class,如下圖 2.伺服器端許可權問題 解決方案:在controller.ashx(我用的.net版本)中添加相關的權 ...
  • 今天寫問卷的時候遇到個label點擊的時候,監聽的click事件被執行兩次;產生這個的原因麽。。。事件冒泡 然後麽找了下方法。。。 方法一:把label扔了。。。 然後方法二 只認input,判斷事件源為input(這是網上有人貼出來的解決方法)http://www.cnblogs.com/feng ...
  • border radius 圓角是做網頁永遠繞不過的話題,以前基本是通過背景圖片做的,有了 CSS3 以後通過屬性就 能夠搞定,我們可以通過 border radius 設置元素的圓角半徑。 對於一個正方形,我們只需要設置為邊長的一半就可以呈現一個圓。 "代碼" border radius 是縮寫的 ...
  • JS自動類型轉換 var a = 1; var b = true; "==" 表示 可以自動類型轉換,比較的是數值 " " 表示可以自動類型轉換,先比較數值,再比較類型 if (a == b) { alert("相等"); //列印 }else{ alert("不等"); } 三目運算 var c ...
  • 客戶端通過構建HTable對象來與HBase集群交互。 要創建HTable對象,首先要創建一個帶有HBase集群信息的配置對象Configuration conf,其一般創建方法如下: 在擁有了conf之後,可以通過HTable提供的如下兩種構造方法來創建HTable對象: (1)直接利用conf來 ...
  • 資料庫同步問題 1.有一臺主資料庫伺服器A和另外一臺資料庫伺服器B,客戶端首先訪問資料庫B,當B資料庫伺服器掛掉時就訪問A,當對資料庫B進行DML操作時,同時對A進行更新,如果A與B之間通訊失敗,則將更新後數據存入臨時表,當恢復通訊時,自動更新,並將臨時數據刪除,同樣當B不通時,將數據臨時存在A中, ...
  • 在資料庫的邏輯結構中,表空間將不同類型的數據分別組織在一起,如系統數據、用戶數據、臨時數據、回滾數據等。在同一個表空間中,數據以資料庫對象為單位組織在一起,一般情況下一個資料庫對象對應一個段,一個表空間中包含多個段。在段中存儲資料庫對象中的數據,數據所占用的存儲空間以區為單位進行分配和回收。 一個數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...