code

MySQL에서 고유 ID를 생성하는 방법은?

starcafe 2023. 9. 25. 22:52
반응형

MySQL에서 고유 ID를 생성하는 방법은?

PHP MySQL ID(됨: 를) 와 같은 .gHYtUUi5b할 수 PHP에서 그런 숫자를 생성할 수 있는 기능들을 많이 찾았는데 ID가 고유한지 어떻게 해야 할지 두렵습니다!

업데이트: uuid는 깁니다. 즉, (P5Dc) 11자의 영숫자를 의미합니다.

편집: 이 답변은 데이터베이스를 파괴하는 상황에서 위험하다는 플래그가 지정되었습니다.데이터베이스에서 고유 ID를 생성할 때 이 코드를 사용하지 마십시오!

UUID()를 사용하여 고유 값을 만듭니다.

예:

insert into Companies (CompanyID, CompanyName) Values(UUID(), "TestUUID");

당신은 우리가 하는 방식을 좋아할 것입니다.저는 꽤 흔한 문제인 "무작위"로 보이는 가역적인 고유 코드를 원했습니다.

  • 우리는 1,942와 같은 입력 번호를 받습니다.
  • 왼쪽 패드를 문자열로 "0000001942".
  • 마지막 두 자리를 앞으로 내세요: "4200000019"
  • 숫자로 변환: 4,200,000,019

우리는 이제 통화마다 엄청난 차이가 있고 100,000,000,000 미만이 보장되는 숫자를 갖게 되었습니다.나쁘지 않은 시작입니다.

  • 이 숫자를 기본 34 문자열로 변환합니다. "2oevc0b"
  • 임의의 0을 'y'로 바꾸고 임의의 0을 'z'로 바꿉니다: "2oevcyb"
  • 업시프트: "2OEVCYB"

base 34를 선택한 이유는 0/O 및 1/l 충돌을 걱정하지 않기 위해서입니다.이제 긴 데이터베이스 식별자를 조회하는 데 사용할 수 있는 짧은 임의로 보이는 키가 있습니다.

프로그래밍 방식은 다음과 같습니다.

  • 필드에 유니크 인덱스 추가
  • PHP에서 랜덤 문자열을 생성합니다.
  • 루프 인 PHP (while(! DO_THE_INSERT ))
    • 다른 문자열을 생성합니다.

참고:

  • 이는 더러울 수 있지만 DBMS와 무관하다는 장점이 있습니다.
  • DBMS 고유 ID 생성기 함수(UUID 등)를 사용하도록 선택한 경우에도 인덱스를 사용하여 필드가 고유해야 함을 보장하는 것이 좋습니다.
  • 루프는 통계적으로 전혀 실행되지 않으며 삽입 실패 시에만 입력됩니다.

버전이 5.7.4보다 높은 MySQL을 사용하는 경우 새로 추가된 RANDOM_BYTES 함수를 사용할 수 있습니다.

 SELECT TO_BASE64(RANDOM_BYTES(16));

됩니다와 됩니다.GgwEvafNLWQ3+ockEST00A==.

unique_ids를 생성하는 방법은 유용한 질문이지만 생성 시기에 대한 생산적인 가정을 하고 있는 것 같습니다.

제 요점은 행을 생성할 때 이러한 고유 ID를 생성할 필요가 없다는 것입니다. 왜냐하면 이 ID들은 삽입되는 데이터와 본질적으로 독립적이기 때문입니다.

제가 하는 일은 미래에 사용할 수 있도록 고유 ID를 미리 생성하는 것입니다. 그렇게 하면 저만의 달콤한 시간을 가질 수 있고 고유하다는 것을 절대적으로 보장할 수 있고, 삽입할 때 수행해야 할 처리가 없습니다.

예를 들어 order_id가 포함된 주문 테이블이 있습니다.이 ID는 사용자가 주문을 입력하면 즉시 생성됩니다. 증분으로 1,2,3 등.사용자는 이 내부 ID를 볼 필요가 없습니다.

그러면 unique_ids 와 (order_id, unique_id)가 있는 다른 테이블이 있습니다.저는 매일 밤 이 테이블에 unique_id 행을 미리 로드하여 향후 24시간 안에 삽입될 수 있는 주문을 처리하는 루틴이 있습니다. (하루에 100,000개의 주문이 들어오면 문제가 발생하지만, 이는 좋은 문제입니다!)

이 접근 방식은 고유성을 보장하며, 사용자에게 영향을 미치지 않는 배치 루틴 및 삽입 트랜잭션에서 모든 처리 부하를 제거합니다.

UUID 함수를 사용합니다.

저는 당신의 프로시저가 고유한 값을 생성하는 PHP의 출처를 모릅니다.만약 그것이 도서관 기능이라면 그들은 당신의 가치가 정말로 독특하다는 것을 보장해야 합니다.문서를 체크인합니다.당신은 이 기능을 항상 사용해야 합니다.예를 들어 PHP 함수를 사용하여 고유 값을 생성한 다음 MySQL 함수를 사용하기로 결정하면 이미 존재하는 값을 생성할 수 있습니다.이 경우 열에 UNIQUE INDEX를 넣는 것도 좋습니다.

DELIMITER $$

USE `temp` $$

DROP PROCEDURE IF EXISTS `GenerateUniqueValue`$$

CREATE PROCEDURE `GenerateUniqueValue`(IN tableName VARCHAR(255),IN columnName VARCHAR(255)) 
BEGIN
    DECLARE uniqueValue VARCHAR(8) DEFAULT "";
    DECLARE newUniqueValue VARCHAR(8) DEFAULT "";
    WHILE LENGTH(uniqueValue) = 0 DO
        SELECT CONCAT(SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1)
                ) INTO @newUniqueValue;
        SET @rcount = -1;
        SET @query=CONCAT('SELECT COUNT(*) INTO @rcount FROM  ',tableName,' WHERE ',columnName,'  like ''',newUniqueValue,'''');
        PREPARE stmt FROM  @query;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    IF @rcount = 0 THEN
            SET uniqueValue = @newUniqueValue ;
        END IF ;
    END WHILE ;
    SELECT uniqueValue;
    END$$

DELIMITER ;

그리고 저장 프로시저를 GenerateUniqueValue('tableName', 'columnName')라고 부릅니다.이렇게 하면 매번 8자리 고유의 캐릭터가 나옵니다.

고유하고 무작위하게 보이는 토큰을 얻으려면 기본 키를 암호화하면 됩니다.

SELECT HEX(AES_ENCRYPT(your_pk,'your_password')) AS 'token' FROM your_table;

이 정도면 충분하고 가역적이기 때문에 테이블에 토큰을 저장할 필요가 없고 대신 생성해야 합니다.

또 다른 장점은 토큰에서 PK를 해독하면 테이블 위에서 많은 양의 전체 텍스트 검색을 수행할 필요가 없고 단순하고 빠른 PK 검색을 수행할 수 있다는 것입니다.

하지만 한가지 작은 문제가 있습니다.MySql은 다른 블록 암호화 모드를 지원하므로 변경하면 토큰 공간이 완전히 변경되어 오래된 토큰을 사용할 수 없게 됩니다.

이를 극복하기 위해 토큰을 생성하기 전에 변수를 설정할 수 있습니다.

SET block_encryption_mode = 'aes-256-cbc';

하지만 그건 좀 아까운데...이를 위한 해결책은 토큰에 마커를 사용한 암호화 모드를 부착하는 것입니다.

SELECT CONCAT(CONV(CRC32(@@GLOBAL.block_encryption_mode),10,35),'Z',HEX(AES_ENCRYPT(your_pk,'your_password'))) AS 'token' FROM your_table;

테이블에서 토큰을 계속 사용하려면 다른 문제가 발생할 수 있습니다.INSERT생성하려면 아직 삽입되지 않은 레코드에 대해 primary_key를 알아야 하기 때문에...물론 당신은 그냥INSERT그리고 나서.UPDATE와 함께LAST_INSERT_ID()다시 말하지만 - 더 나은 해결책이 있습니다.

INSERT INTO your_table ( token )
SELECT CONCAT(CONV(CRC32(@@GLOBAL.block_encryption_mode),10,35),'Z',HEX(AES_ENCRYPT(your_pk,'your_password'))) AS 'token'
FROM information_schema.TABLES 
WHERE  TABLE_SCHEMA = DATABASE() AND TABLE_NAME = "your_table";

이 솔루션의 마지막 장점은 php, python, js 또는 사용할 수 있는 다른 언어로 쉽게 복제할 수 있다는 것입니다.

아래는 숫자 고유 랜덤 ID...를 참조하기 위한 것입니다.

도움이 될지도...

$query=mysql_query("select * from collectors_repair");
$row=mysql_num_rows($query);
$ind=0;
if($row>0)
{
while($rowids=mysql_fetch_array($query))
{
  $already_exists[$ind]=$rowids['collector_repair_reportid'];
}
}
else
{
  $already_exists[0]="nothing";
}
    $break='false';
    while($break=='false'){
      $rand=mt_rand(10000,999999);

      if(array_search($rand,$alredy_exists)===false){
          $break='stop';
      }else{

      }
    }

 echo "random number is : ".$echo;

그리고 ->와 같은 코드로 char를 추가할 수 있습니다.$rand=mt_rand(10000,999999) .$randomchar; // assume $radomchar contains char;

고유성을 위해 유닉스 타임스탬프를 가져다가 임의의 문자열을 추가하여 사용합니다.

crypt()제안한 대로 salt를 일부 구성 파일에 저장하고 salt를 1부터 시작하고 중복되는 것을 발견하면 다음 값 2로 이동합니다.두 개의 차를 사용할 수 있지만, 소금을 넣기에 충분한 조합이 됩니다.

문자열을 생성할 수 있습니다.openssl_random_pseudo_bytes(8). 따라서 이것은 임의적이고 짧은 문자열(11 char)을 제공해야 합니다.crypt().

결과에서 소금을 제거하면 무작위로 실패할 때마다 소금을 바꾸면 1억 개 이상의 사람들이 충분히 무작위해야 할 11개의 문자만 있을 것입니다.

사용하는 것도 고려해 볼 수 있습니다.crypt()*제약 조건 내에 [거의 보장된] 고유 ID를 생성합니다.

 <?php
    $hostname_conn = "localhost";
    $database_conn = "user_id";
    $username_conn = "root";
    $password_conn = "";
     $conn = mysql_pconnect($hostname_conn, $username_conn,   $password_conn) or trigger_error(mysql_error(),E_USER_ERROR); 
   mysql_select_db($database_conn,$conn);
   // run an endless loop      
    while(1) {       
    $randomNumber = rand(1, 999999);// generate unique random number               
    $query = "SELECT * FROM tbl_rand WHERE the_number='".mysql_real_escape_string ($randomNumber)."'";  // check if it exists in database   
    $res =mysql_query($query,$conn);       
    $rowCount = mysql_num_rows($res);
     // if not found in the db (it is unique), then insert the unique number into data_base and break out of the loop
    if($rowCount < 1) {
    $con = mysql_connect ("localhost","root");      
    mysql_select_db("user_id", $con);       
    $sql = "insert into tbl_rand(the_number) values('".$randomNumber."')";      
    mysql_query ($sql,$con);        
    mysql_close ($con);
    break;
    }   
}
  echo "inserted unique number into Data_base. use it as ID";
   ?>

사용하기

    $info = random_bytes(16);
    $info[6] = chr(ord($info[6]) & 0x0f | 0x40); 
    $info[8] = chr(ord($info[8]) & 0x3f | 0x80); 
    $result =vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($info), 4));
    return $result;

이렇게 하면 랜덤 ID가 생성됩니다.

CREATE TABLE Persons (
    ID Integer PRIMARY KEY AUTOINCREMENT,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int
);

트위터의 눈송이를 사용할 수 있습니다.

즉, 시간, 서버 ID, 시퀀스를 기반으로 고유 ID를 생성합니다.64비트 값을 생성하므로 상당히 작고 INT64에 적합합니다.값을 올바르게 정렬할 수도 있습니다.

https://developer.twitter.com/en/docs/basics/twitter-ids

요약하면 여러 대의 서버, 높은 동시성, 정렬 값 등을 모두 64비트로 처리할 수 있습니다.

여기 MySQL에 대한 구현이 있습니다.

https://github.com/EFTEC/snowflake-mysql

함수와 표로 구성되어 있습니다.

검색한 결과 이 기사를 발견했습니다.

계획 A: UUID 또는 GUID.

플랜 B: 랜드:

SELECT FLOOR(rand() * 90000 + 10000);

계획 C: 전체 MD5:

SELECT MD5(NOW());

계획 D: MD5의 일부:

SELECT LEFT(MD5(NOW()), 4);

계획 E: 암호화/복호화

SELECT HEX(AES_ENCRYPT(123, 'foo')); 
SELECT AES_DECRYPT(UNHEX('C7FC2E77A3D894D2BA02F2214E37F107'), 'foo');

언급URL : https://stackoverflow.com/questions/1467581/how-to-generate-unique-id-in-mysql

반응형