2012-12-01 53 views
3

我正在使用PHP/MySQL。檢查用戶名是否已被使用的最佳方法是什麼?如何正確檢查用戶名是否被採用?

現在我所做的只是執行select語句來查看用戶名是否已被佔用。如果select返回一行然後我停止並顯示一條錯誤消息。如果select沒有返回任何內容,那麼我插入新的用戶。

但是有沒有更高效的方法?例如,我可以在用戶名列上使用UNIQUE,然後只執行一條插入語句(如果插入語句已被佔用,則會從插入語句中獲取錯誤)。

+0

Ofourse您可以在用戶名列上使用UNIQUE,否則給予某人一個UNIQUE用戶名有什麼意義......;)[請檢查此問題](http://stackoverflow.com/questions/) 12829405/insert-statement) – bonCodigo

回答

5

您確實有一些其他線程會在您的SELECT確認該用戶不存在與您插入它的INSERT之間的短暫時刻插入您的用戶名。這被稱爲race condition

它可能看起來像這種事情發生的機率是很小的,但是有一個說法有關:「One in a million is next Tuesday.

是,在用戶名UNIQUE約束可以防止你插入一個重複的用戶名。聲明那個約束。

有些文章會告訴你,一旦你有一個UNIQUE約束,你就不必再做SELECT了。只需嘗試 INSERT,如果它衝突,則報告錯誤。

但是,我幫助一個網站從這個技術引起的問題恢復。在他們的網站上,用戶試圖很快創建新的用戶名,並導致INSERT上的很多衝突。問題是,MySQL increments the auto-increment primary key for the table, even if the INSERT was canceled。而這些自動增量值永遠不會被重用。所以結果是他們每個成功的INSERT失去了1000-1500個ID號碼。當他們的INT主鍵達到2 -1時,他們打電話給我,他們無法在表中創建另一行!

他們使用的解決方案是首先嚐試SELECT,並報告重複。然後,如果看起來很安全,請嘗試INSERT - 但編寫代碼以處理與UNIQUE約束可能的衝突,因爲競爭條件仍然可能發生。

+0

爲什麼他們不能僅僅事務處理select和insert? – FoolishSeth

+0

偉大的觀點和軼事! – inhan

+1

@FoolishSeth,SELECT不鎖定任何東西,所以它不會阻塞任何併發的INSERT。如果您開始交易,這沒有幫助。 –

相關問題