Re: [請益] 請問關於不重複編號
※ 引述《koizumisyou (不小的挑戰)》之銘言:
: 我的需求為用戶端送出一個表單時
: 編號為 920904001,若重複,則取該欄位最大值+1
: 9為固定號碼,2為西元年最後一碼,0904為日期,001是流水編
: 為了不重複,參考網路作法
: 1、變數C預設值是當天的001
: 2、假設經比對 變數 total不等於0,也就是裡頭已經有該編號
: 3、那麼就取最大值+1
: 我的問題是
: 問題1:為什麼多人使用時還是會重複編號??
: 問題1-1:重複的編號我觀察結果發現,重複的編號都是我自己輸入資料編號的最大值,不是整個資料庫的
: 問題2:整個網頁重新整理以後就好了
大部份 LaPass 大大 都講完了 :Q
會有這個狀況簡單來說,就是程式在執行上無法作到資源獨占這件事,
不單是 DB,只要是任何有資源取用 / 異動的地方永遠都會有這個問題。
你可以把這個檔案 copy 一次,
在其中一個檔案裡的 insert 前 sleep 個 60 秒然後兩隻一起送出看看,
撞 key 是非常容易的 XD
##
要能確保資源獨占,一是極小化(或著該說是極快化)程式的存取,
讓在自己從存取到異動的過程裡不會遇到別人,實際上這種很難有保障
以你的例子而言,是可以嘗試把東西轉成一道 sql 餵進去,像這樣:
$A = date("md") ;//變數A:9開頭加上帶零的月、日
$B = substr(date('Y'),3,1);//變數B:取西元年第3個字元後1碼
$C = Sprintf("9$B$A%s",'001') ; //變數B前加9,變數A後加001
// 以上你原本的 code 我不動
$D = "9$B$A"; // 我需要這個 :P
mysql_select_db($database_AdvList, $AdvList);
$sql =
" INSERT INTO `advlist` (`advID`) ".
" SELECT IF(`advID`<'$C', '$C',".
" CONCAT('$D', LPAD(RIGHT(`advID`, 3)+1, 3, '0')))".
" FROM `advlist` ORDER BY `advID` DESC LIMIT 1";
// 用 INSERT SELECT 來做,
// 如果拿到的最後一筆 advID 比今天的第一筆要小,就給值今天第一筆
// 如果最後一筆大於 / 等於今天的第一筆,則取末三位+1,再補零塞回去
當然這無法在 mysql 自己都很慢的時候還保證不撞 key…
##
資源獨占另一種就是 lock,只要能確定「在我使用的期間,別人不可以動」,
那麼就能作到確保資源獨占,
mysql 本身有 lock table 的語法
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
如果你要比較高的保障,用 lock 一定是最有效的,
但是在大量瞬間多人寫入的時候會有較長的 waiting(因 DB lock 頁面開不起來)
或著我建議…這種不是很重要的序列編碼,應該是由 auto increment 來處理掉,
然後看是要另外開一個 field / table 負責存每天第一筆的差值(其實也不需要)
還是怎樣的… XD
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 1.161.193.130
討論串 (同標題文章)
PHP 近期熱門文章
PTT數位生活區 即時熱門文章