2010-11-19 68 views
7

Tôi đã tự hỏi nếu có ai biết một cách tốt để tạo ra một số nguyên ngẫu nhiên duy nhất cho một khóa chính cho một bảng. Tôi đang sử dụng MySQL. Giá trị phải là số nguyên.Làm thế nào để tạo ID nguyên duy nhất ngẫu nhiên cho khóa chính cho bảng?

+2

tại sao không chỉ 'AUTO_INCREMENT' ? – RobertPitt

+2

Vì tôi muốn sử dụng giá trị đó để mã hóa thành Base62 và sau đó sử dụng giá trị đó cho một id trong url. Nếu tôi tự động tăng, nó có thể là rõ ràng cho người sử dụng như thế nào id id được tạo ra. – MindGame

+3

Để khắc phục sự cố bảo mật của bạn, bạn có thể sử dụng AUTO_INCREMENT và bao gồm số được tạo ngẫu nhiên làm trường. Để có userid của bạn, bạn lấy id AUTO + số ngẫu nhiên đó. Chạy nó thông qua một băm (SHA128 sẽ làm việc tốt). Ngay cả khi số ngẫu nhiên là giống nhau (mà nó thực tế sẽ không được), kết hợp nó với một số khác sau đó SHA'ing nó sẽ cung cấp cho bạn userid của bạn. – g19fanatic

Trả lời

5

Nếu bạn đang mở đề xuất và bạn có thể triển khai, hãy sử dụng UUID. Chức năng UUID() của MySQL sẽ trả lại giá trị 36 ký tự có thể được sử dụng cho ID.

Nếu bạn muốn sử dụng số nguyên, tôi nghĩ bạn cần tạo hàm getRandID() mà bạn sẽ sử dụng trong câu lệnh INSERT. Hàm này cần sử dụng ngẫu nhiên + kiểm tra các id hiện có để trả về một id không được sử dụng trước đó.

Kiểm tra chức năng RAND() cho MySQL.

+0

Làm cách nào để đảm bảo rằng giá trị ngẫu nhiên không được sử dụng bởi một người khác cùng một lúc. Ví dụ người A và B có cùng số ngẫu nhiên.Cả hai kiểm tra cùng một lúc nếu nó tồn tại, nó không như vậy cả hai đều chèn. Tất nhiên, một lỗi vì ràng buộc khóa chính. Bạn làm gì để đi xung quanh? Khóa bàn? Không bao giờ sử dụng nó và không thoải mái khi sử dụng nó. – MindGame

+0

Đó là vẻ đẹp của UUID (Số nhận dạng duy nhất toàn cầu). Trích dẫn Wikipedia: "Mục đích của UUID là để cho phép các hệ thống phân tán nhận dạng duy nhất thông tin mà không có sự phối hợp trung tâm đáng kể. Do đó, bất cứ ai cũng có thể tạo ra một UUID và sử dụng nó để xác định điều gì đó với sự tin tưởng hợp lý. Do đó, thông tin được gắn nhãn với UUID có thể được kết hợp lại thành một cơ sở dữ liệu duy nhất mà không cần giải quyết xung đột tên. " –

+1

@Tôi sẽ chỉ lặp lại hàm trong CATCH khi ngoại lệ phát sinh do ràng buộc UNIQUE và tiếp tục cho đến khi bạn có thể chèn một hàng với Id ngẫu nhiên đó. –

0

Có một tính năng AUTO_INCREMENT. Tôi sẽ sử dụng nó.

Xem here ví dụ khác.

0

AUTO_INCREMENT sẽ là cách tốt nhất cho bạn.

Here là một số ví dụ.

Nếu bạn cần, bạn có thể điều chỉnh nơi giá trị gia tăng bắt đầu (theo mặc định là 1).

12

Để đối phó với:."Bởi vì tôi muốn sử dụng giá trị đó để mã hóa để Base62 và sau đó sử dụng cho một id trong url Nếu tôi increment tự động, nó có thể là hiển nhiên đối với người sử dụng như thế nào id url được tạo ra."

Nếu bảo mật là mục tiêu của bạn thì hãy sử dụng Base62, ngay cả với số được tạo "ngẫu nhiên" sẽ không hữu ích.

Một lựa chọn tốt hơn sẽ:

  • Đừng tái phát minh ra bánh xe - sử dụng AUTO_INCREMENT
  • Sau đó sử dụng một hàm băm mật mã + một chuỗi được tạo ngẫu nhiên (ẩn trong db cho rằng url cụ thể) để tạo ra "id duy nhất cho rằng url" thức
+1

Cảm ơn bạn đã trả lời. Được rồi, tôi sử dụng tăng tự động và sau đó sử dụng hàm băm mật mã + chuỗi được tạo ngẫu nhiên. Nhưng tôi cần url của tôi để được ngắn. Ngắn như thế nào tinyurl hiện nó. Bằng cách sử dụng mật mã, tôi sẽ không nhận được "id duy nhất cho url đó" dài không? – MindGame

7

làm thế nào bạn tạo ra unique_ids là một câu hỏi hữu ích - nhưng bạn dường như được thực hiện một giả định năng suất truy cập về khi bạn gen đánh giá chúng!

Điểm của tôi là bạn không cần phải tạo các id duy nhất này tại thời điểm tạo hàng của bạn, bởi vì về cơ bản chúng độc lập với dữ liệu được chèn vào.

Những gì tôi làm là tạo trước id duy nhất để sử dụng trong tương lai, theo cách đó tôi có thể dành thời gian ngọt ngào của riêng mình và đảm bảo chúng độc đáo và không cần xử lý tại thời điểm chèn.

Ví dụ: tôi có bảng đơn đặt hàng có order_id trong đó. Id này được tạo khi đang di chuyển khi người dùng nhập vào thứ tự, tăng dần 1,2,3 vv mãi mãi. Người dùng không cần phải xem id nội bộ này.

Sau đó, tôi có một bảng khác - unique_ids với (order_id, unique_id).Tôi có một thói quen chạy mỗi đêm mà trước khi tải bảng này với đủ các hàng unique_id để hơn bao gồm các đơn đặt hàng có thể được chèn vào trong 24 giờ tới. (Nếu tôi nhận được 10000 đơn đặt hàng trong một ngày, tôi sẽ gặp vấn đề - nhưng đó sẽ là một vấn đề tốt để có!)

Cách tiếp cận này đảm bảo tính duy nhất và lấy bất kỳ tải xử lý nào từ giao dịch chèn và vào lô thường xuyên, nơi nó không ảnh hưởng đến người dùng.

1

Làm thế nào về phương pháp này (PHPMySQL):


ngắn

  1. Tạo ngẫu nhiên number cho user_id (UNIQUE)
  2. Chèn hàng với tạo number như user_id
  3. Nếu inse số hàng rted bằng 0, đi tới điểm 1

Trông nặng? Tiếp tục đọc.


dài:

Bảng:

users (user_id int UNIQUE) 

Code:

<?php 
// values stored in configuration 
$min = 1; 
$max = 1000000; 

$numberOfLoops = 0; 
do { 
    $randomNumber = rand($min, $max); 

    // the very insert 
    $insertedRows = insert_to_table(
     'INSERT INTO foo_table (user_id) VALUES (:number)', 
     array(
      ':number' => $randomNumber 
     )); 

    $numberOfLoops++; 

    // the magic 
    if (!isset($reported) && $numberOfLoops/10 > 0.5) { 
     /** 
     * We can assume that at least 50% of numbers 
     * are already in use, so increment values of 
     * $min and $max in configuration. 
     */ 
     report_this_fact(); 
     $reported = true; 
} while ($insertedRows < 1); 

  1. Al Giá trị l ($min, $max, 0.5) chỉ để giải thích và chúng không có ý nghĩa thống kê.
  2. Chức năng insert_to_tablereport_this_fact không được xây dựng bằng PHP. Đây cũng là những con số chỉ để làm rõ các mục đích giải thích.
0

theo cách của tôi, cho cả nền tảng 32 bit và 64bit. Kết quả là 64bit

function hexstr2decstr($hexstr){ 
    $bigint = gmp_init($hexstr, 16); 
    $bigint_string = gmp_strval($bigint); 
    return $bigint_string; 
} 

function generate_64bitid(){ 
    return substr(md5(uniqid(rand(), true)), 16, 16); 
} 

function dbGetUniqueXXXId(){ 
    for($i = 0; $i < 10; $i++){ 
     $decstr = hexstr2decstr(generate_64bitid()); 

     //check duplicate for mysql.tablexxx 
     if($dup == false){ 
      return $decstr; 
     } 
    } 
    return false; 
} 
0

Bạn có thể sử dụng một AUTO_INCREMENT cho bảng của bạn, nhưng cung cấp cho những người sử dụng phiên bản mã hóa:

ENCRYPTED_ID: SELECT HEX(AES_ENCRYPT(id, 'my-private-key'));

id: SELECT AES_DECRYPT(UNHEX(encrypted_id), 'my-private-key');

Các vấn đề liên quan