基於類別的唯一程式碼 - 一種 auto_increment
我必須為每個註冊的使用者創建一個唯一的程式碼。問題是需要根據使用者來自哪個城市生成唯一程式碼。所以我的桌子是:
CREATE TABLE `microreg`.`users` ( `user_id` INT NOT NULL AUTO_INCREMENT , `user_code` CHAR(10) NOT NULL , PRIMARY KEY (`user_id`), UNIQUE (`user_code`));
user_id
用於唯一標識數據庫中的使用者。
user_code
是為使用者使用而生成的可讀程式碼。他們使用該唯一程式碼訪問他們的帳戶。CREATE TABLE `microreg`.`districts` ( `district_id` INT NOT NULL AUTO_INCREMENT , `district_name` VARCHAR(50) NOT NULL , `district_code` CHAR(4) NOT NULL , PRIMARY KEY (`district_id`), UNIQUE (`district_code`));`
這包含大約 20K 個分配了唯一程式碼的地區。
說,
Trichy ITRY Coimbatore ICBE Kolkata IKOL Delhi IDEL ... New York UNYK Washington UWDC
因此,當使用者以 Trichy 註冊為地區時,他將生成
user_id : 1 user_code : ITRY000001
同一城市的第二個使用者
user_id : 2 user_code : ITRY000002
另一個來自紐約
user_id : 3 user_code : UNYK000001
user_code 在地區方面是唯一的。
$$ User with id 1 and 3 are not same $$ 到目前為止,我獲取了使用者所選區域的最大值
SELECT RIGHT(MAX(user_code),6) FROM `users` WHERE user_code LIKE 'ITRY%';
然後將其增加 1,然後將其添加回來並附加 District_code。
INSERT INTO `microreg`.`users` (`user_id`, `user_code`) VALUES (NULL, 'ITRY000003');
當一次只有一個使用者更新時,此方法非常有效。但是當多個使用者同時開始註冊時,這開始產生問題。由於設置了唯一性,因此生成了兩個具有相同 user_code 的使用者並產生了成本。
以前,對於另一個應用程序,我為每個程式碼創建了唯一的表(如這裡的地區)並將使用者添加到該表中,然後附加回原始表(如這裡的使用者)。在那種情況下,我只有 4 種類型的程式碼(比如這裡的區)。但是對於這個應用程序,我有大約 20K 個區。我無法得到這個火花。(有關資訊,我在此應用程序中使用 PHP 和 mysqli)謝謝。
如果您有多個編寫器,則選擇最大值和增量不會縮放。我的經驗法則是,如果您需要為日常操作鎖定表,您應該認真質疑您是否有正確的解決方案。
是否要求使用者程式碼單調遞增 1?我認為 MySQL 除了 auto_increment 工具之外沒有其他序列。我假設您不想公開 user_id 列。
如果不需要增加 1,我提供兩種解決方案。
- 創建一個表,其唯一目的是使用 auto_increment 功能生成一個序列。它有兩列,user_id 和 seqno(那一列是自動增量)。您將使用 user_id 插入一行並獲取該使用者的 seqno。與分區連接以生成使用者程式碼。您可以在創建使用者後刪除該行。
- 散列 user_id 和與地區的連接。
為了簡單起見,我偏愛第二種解決方案。
假設您使用的是符合 ACID 的引擎(即 InnoDB),如果包裝在事務中,“獲取最大值,添加一個,然後插入”方法應該可以工作。
我會查詢使用者程式碼的要求是一個特定的項目,儘管你有一個使用者 ID,它可能是一個自動遞增的整數。如果不需要程式碼在一個區域內是連續的(即可以有 ITRY000003 和 ITRY000042 但兩者之間沒有,因為使用者 4 到 41 在其他地方),那麼您可以將使用者程式碼作為派生值構造從
$$ district_code $$+PadWithZeros($$ user_id $$)。這意味著您不必擔心生成額外的程式碼(我認為這主要用於顯示目的?)。如果使用者可以在地區之間移動,您可能仍需要儲存它,但如果他們這樣做,您希望保留他們的原始程式碼。如果使用者移動區域時不需要程式碼是靜態的,那麼您不需要儲存它:它可以在需要時導出。