MySQL에서 UUIDv4를 생성하는 방법은 무엇입니까?
MySQLUUID
function이 UUIDv1 GUID를 반환합니다.SQL에서 임의의 GUID(예: UUIDv4)를 쉽게 생성할 수 있는 방법을 찾고 있습니다.
저는 솔루션을 찾는 데 상당한 시간을 들였고 표준 MySQL 함수를 사용하여 랜덤 UUID(즉, UUIDv4)를 생성하는 다음과 같은 mysql 함수를 생각해냈습니다.저는 그것이 유용하기를 바라며 그것을 공유하기 위해 저만의 질문에 답하고 있습니다.
-- Change delimiter so that the function body doesn't end the function declaration
DELIMITER //
CREATE FUNCTION uuid_v4()
RETURNS CHAR(36) NO SQL
BEGIN
-- Generate 8 2-byte strings that we will combine into a UUIDv4
SET @h1 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');
SET @h2 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');
SET @h3 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');
SET @h6 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');
SET @h7 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');
SET @h8 = LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0');
-- 4th section will start with a 4 indicating the version
SET @h4 = CONCAT('4', LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'));
-- 5th section first half-byte can only be 8, 9 A or B
SET @h5 = CONCAT(HEX(FLOOR(RAND() * 4 + 8)),
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'));
-- Build the complete UUID
RETURN LOWER(CONCAT(
@h1, @h2, '-', @h3, '-', @h4, '-', @h5, '-', @h6, @h7, @h8
));
END
//
-- Switch back the delimiter
DELIMITER ;
참고: 사용된 의사 난수 생성(MySQL's)RAND
)는 암호화적으로 안전하지 않으므로 충돌 위험을 증가시킬 수 있는 일부 편향이 있습니다.
두 가지 기존 답변은 모두 MySQL 함수에 의존합니다.
랜드()는 완벽한 랜덤 생성기가 아닙니다.이는 동일한 MySQL 버전의 플랫폼 간에 이동할 수 있는 온디맨드 랜덤 번호를 빠르게 생성할 수 있는 방법입니다.
실제로, 이것은 생성된 것을 의미합니다.UUID
이 함수를 사용하면 편향될 수 있으며(그리고 그럴 것이며) 충돌이 예상보다 더 자주 발생할 수 있습니다.
해결책
다음 함수를 사용하여 MySQL 측에서 안전한 UUID V4를 생성할 수 있습니다.
이 함수는 SSL 라이브러리의 난수 생성기를 사용하여 생성된 렌 랜덤 바이트의 이진 문자열을 반환합니다.
따라서 기능을 다음으로 업데이트할 수 있습니다.
CREATE FUNCTION uuid_v4s()
RETURNS CHAR(36)
BEGIN
-- 1th and 2nd block are made of 6 random bytes
SET @h1 = HEX(RANDOM_BYTES(4));
SET @h2 = HEX(RANDOM_BYTES(2));
-- 3th block will start with a 4 indicating the version, remaining is random
SET @h3 = SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3);
-- 4th block first nibble can only be 8, 9 A or B, remaining is random
SET @h4 = CONCAT(HEX(FLOOR(ASCII(RANDOM_BYTES(1)) / 64)+8),
SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3));
-- 5th block is made of 6 random bytes
SET @h5 = HEX(RANDOM_BYTES(6));
-- Build the complete UUID
RETURN LOWER(CONCAT(
@h1, '-', @h2, '-4', @h3, '-', @h4, '-', @h5
));
END
이렇게 하면 충돌에 관심이 없을 정도로 UUID V4가 랜덤으로 생성됩니다.
참고: 안타깝게도 MariaDB는 지원하지 않습니다.RANDOM_BYTES()
(https://mariadb.com/kb/en/function-differences-between-mariadb-105-and-mysql-80/ #기타 참조)
시험
다음과 같은 테스트 시나리오를 만들었습니다.40.000.000개의 행이 생성될 때까지 임의 UUID v4를 테이블의 기본 키로 삽입합니다.충돌이 발견되면 행이 증분하여 업데이트됩니다.collisions
열:
INSERT INTO test (uuid) VALUES (uuid_v4()) ON DUPLICATE KEY UPDATE collisions=collisions+1;
각 기능이 있는 4천만 행 이후의 충돌 합계는 다음과 같습니다.
+----------+----------------+
| RAND() | RANDOM_BYTES() |
+----------+----------------+
| 55 | 0 |
+----------+----------------+
두 시나리오 모두 행 수가 증가함에 따라 충돌 횟수가 증가하는 경향이 있습니다.
DB로 작업 중이고 함수를 생성할 Perm이 없을 경우 SQL 식과 동일한 버전이 다음과 같습니다.
SELECT LOWER(CONCAT(
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
'4',
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
HEX(FLOOR(RAND() * 4 + 8)),
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0')));
다음을 이용한 엘리아스 소아레스의 답변 적용RANDOM_BYTES
DB 함수를 생성하지 않고 다음을 수행합니다.
SELECT LOWER(CONCAT(
HEX(RANDOM_BYTES(4)), '-',
HEX(RANDOM_BYTES(2)), '-4',
SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3), '-',
CONCAT(HEX(FLOOR(ASCII(RANDOM_BYTES(1)) / 64)+8),SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3)), '-',
HEX(RANDOM_BYTES(6))
))
언급URL : https://stackoverflow.com/questions/32965743/how-to-generate-a-uuidv4-in-mysql
'source' 카테고리의 다른 글
fs 수정 방법: 네이티브 모듈 소스 재평가는 지원되지 않습니다' - graceful-fs (0) | 2023.08.27 |
---|---|
MariaDB를 제거하고 MySQL for Postfix를 설치하는 방법은 무엇입니까? (0) | 2023.08.27 |
경고: 할당은 캐스트 없이 포인터의 정수를 만듭니다. (0) | 2023.08.27 |
이전에 안정적이었던 Docksal 구현에 대한 새로운 문제 (0) | 2023.08.27 |
배경 이미지로 제공될 때 SVG 이미지의 채우기 색상을 수정하는 방법은 무엇입니까? (0) | 2023.08.27 |