あなたのアルゴリズムは問題なく (DB API モジュールが安全である限り、スレッドセーフです)、おそらく最善の方法です。重複することはありませんが(sidにPRIMARYまたはUNIQUEキーがあると仮定)、IntegrityError
INSERTで例外が発生する可能性はほとんどありません。しかし、あなたのコードは見栄えがよくありません。再帰の代わりに試行回数を制限したループを使用することをお勧めします (コードに何らかのエラーが発生した場合、無限になる可能性があります)。
for i in range(MAX_ATTEMPTS):
sid = os.urandom(8).decode('hex')
db.execute('SELECT COUNT(*) FROM sessions WHERE sid=?', (sid,))
if not db.fetchone()[0]:
# You can catch IntegrityError here and continue, but there are reasons
# to avoid this.
db.execute('INSERT INTO sessions (sid) VALUES (?)', (sid,))
break
else:
raise RuntimeError('Failed to generate unique session ID')
失敗する可能性をさらに小さくするために使用されるランダムな読み取り文字数を上げることができます。base64.urlsafe_b64encode()
SID を短くしたい場合は、あなたの友人ですが、データベースがこの列に対して大文字と小文字を区別する比較を使用していることを確認する必要があります (バイナリ照合を設定しない限り、MySQL の VARCHAR は適切ではありませんが、VARBINARY は問題ありません)。