Re: [請益] 請問關於不重複編號

看板PHP作者 (銀色)時間13年前 (2012/09/05 03:21), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串4/4 (看更多)
※ 引述《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
文章代碼(AID): #1GHbJB7b (PHP)
文章代碼(AID): #1GHbJB7b (PHP)