그누보드5 get_new_uniqid() > 그누보드5 팁자료실

그누보드5 팁자료실

그누보드5 get_new_uniqid() 정보

그누보드5 get_new_uniqid()

본문

https://sir.kr/qa/236514  이 질문글을 보고 동일한 이슈를 겪었던 경험이 있어 코드를 공유합니다.

myisam 에선 트랜젝션이라는 개념이 없어 lock table 을 사용하는데 이건 트랜젝션이 아닙니다. 

 

mysql 버전이 5.0 이상이라면, 그누보드, 영카트 관련된 테이블은 모두  innodb로 바꾸세요. 묻지도 따지지지도 말고 myisam 은 버리고 innodb 로 바꾸세요.

아래코드는 innodb로 변경후 적용하셔야 합니다.

 


function get_new_uniqid() {
    global $g5;
    //README {$g5['uniqid_table']} 테이블을 반드시 innodb로 변경하세요.
    if(function_exists('mysqli_connect') && G5_MYSQLI_USE) {
        $mysqli = $g5['connect_db'];
        $mysqli->begin_transaction();
        try {
            while (1) {
                // 년월일시분초에 100분의 1초 두자리를 추가함 (1/100 초 앞에 자리가 모자르면 0으로 채움)
                $key = date('YmdHis', time()) . str_pad((int)(microtime() * 100), 2, "0", STR_PAD_LEFT);
                $result = $mysqli->query(" insert IGNORE into {$g5['uniqid_table']} set uq_id = '$key', uq_ip = '{$_SERVER['REMOTE_ADDR']}' ", false);
                if ($result) {
                    $mysqli->commit();
                    return $key;
                } // 쿼리가 정상이면 빠진다.
                // insert 하지 못했으면 일정시간 쉰다음 다시 유일키를 만든다.
                usleep(10000); // 100분의 1초를 쉰다
            }
        } catch (Exception $e) {
            $mysqli->rollback();
        }
    } else {
        sql_query("SET AUTOCOMMIT=0");
        sql_query("BEGIN");
        try {
            while (1) {
                // 년월일시분초에 100분의 1초 두자리를 추가함 (1/100 초 앞에 자리가 모자르면 0으로 채움)
                $key = date('YmdHis', time()) . str_pad((int)(microtime() * 100), 2, "0", STR_PAD_LEFT);
                $result = sql_query(" insert into {$g5['uniqid_table']} set uq_id = '$key', uq_ip = '{$_SERVER['REMOTE_ADDR']}' ", false);
                if ($result) {
                    sql_query("COMMIT");
                    sql_query("SET AUTOCOMMIT=1");
                    return $key;
                } // 쿼리가 정상이면 빠진다.
                // insert 하지 못했으면 일정시간 쉰다음 다시 유일키를 만든다.
                usleep(10000); // 100분의 1초를 쉰다
            }
        } catch (Exception $e) {
            sql_query("ROLLBACK");
            sql_query("SET AUTOCOMMIT=1");
        }
    }
}
추천
7

댓글 14개

ALTER TABLE g5_uniqid ENGINE = INNODB;
이 방법으로 엔진을 변경하였는데요.
phpMyAdmin과 PuTTY 둘 다 해보았는데,
show table status like 'g5_uniqid' \G 로 확인해보면
테이블 엔진이 여전히 MyISAM 으로 되어있어서
호스팅사에 왜 변경이 안되는지 문의해놓았어요.

CREATE TABLE IF NOT EXISTS `g5_uniqid_test` (
  `uq_id` bigint(20) unsigned NOT NULL,
  `uq_ip` varchar(255) NOT NULL,
  PRIMARY KEY (`uq_id`)
) ENGINE=innoDB DEFAULT CHARSET=utf8;
이렇게 생성해줘봤는데도,

mysql> show table status like 'g5_uniqid_test' \G
*************************** 1. row ***************************
          Name: g5_uniqid_test
        Engine: MyISAM
        Version: 10
    Row_format: Dynamic
이렇게 MyISAM으로 생성이 되버려요.

그리고 알려주신 get_new_uniqid() 는 innoDB로 변경되지 않았는데도
잘 구동하는 것 같습니다.

테이블 상태가 바뀌었는 줄 알고 스크립트 변경해서 실행해보니,
장바구니와 주문 모두 이상없이 되더라구요.

장바구니에 타인이 넣은 상품이 보여지는것은 아직 확인해보지 못했어요.
우선 테이블 엔진이 제대로 바뀌지 않아서 다시 예전 get_uniqid()로 변경해놓았거든요.

카페24 회신이 오면 재 확인 해보고 댓글 남길께요.

서버환경 UTF-8 (PHP5.5, MySQL5.x)
만약에요. innoDB 엔진으로 변경할 수 없다면,
지금처럼 장바구니에 간혹가다 타인이 넣은 상품리스트가 보여질땐 어떻게 해주어야 할까요?
비회원도 구입 가능한 사이트여서요.

유일키가 어찌되었건 YmdHis 뒤에 숫자2개가 조합된 문자열이잖아요.
여기 사이트가 하루 주문이 일 40~50건인데요.
동일한 유일키가 할당이 되려면 같은날 같은 시분초에 접속하여서
우연히도 백분의 1초 2자리 숫자가 동일해야 하는것이잖아요.

중복으로 할당될 가능성이 이렇게 높은지요?

하루 한두번씩 동일 유일키가 할당이 되어서,
타인이 추가한 장바구니 상품이
또 다른 누군가의 장바구니에 보여지는 현상이 나타나는 것 같아서요.ㅠㅠ
date('YmdHis', time()) . str_pad((int)(microtime() * 100), 2, "0", STR_PAD_LEFT).rand(1111,9999);
혹시, 이렇게 랜덤 숫자를 뒤에 추가해준다면 좀 낫지 않을까요?
정말 만에하나 동시에 백분의 1초까지 똑같게 호출을 해서 같은 값이 나오더라도
랜덤 4자리 숫자까지 같을 가능성은 좀 더 희박할테니까요.ㅠㅠ

다만, 영카트5 전반에 DB나 스크립트상 uniqid 자릿수 제한 둔곳이 있는지,
자릿수가 영향을 주는 부분이 있는지 확인해봐야겠지요.

도움 말씀 좀 부탁드려요. 감사합니다.
기존 MYISAM 형식에서, get_uniqid() 함수안에 키 생성코드에 랜덤숫자 4자리를 추가로 넣어주었어요.
$key = date('ymdHis', time()) . str_pad((int)(microtime()*100), 2, "0", STR_PAD_LEFT) . rand(1111,9999);
자릿수가 biging(20)로 되어있어서 date를 y로 바꿔주었구요.
내일 확인해보고 또 댓글 남길께요.
좋은 정보네요. 감사합니다.
그누보드도 어여 innodb가 기본으로 들어갔으면 좋겠어요.
아니면 선택적으로라도요~~
혹시나 해서 남겨보는 글인데요.

위 코드는 밀리세컨드까지 이용하여 최대한 중복 코드를 막는다는 것으로 보여지는데...
실질적인 해결은 아닌 듯 해서요.

쇼핑몰 영업이 너무나 잘되어
여러 건이 초단위로 장바구니 저장이 이루어진다면 
역시 동일한 문제가 발생하지 않나 해서요...

"for update" 문을 이용하여 Lock(?)을 걸어줘야
완전히 안전해지는게 아닌가 하여 남겨봅니다.

for update 문은
transaction이 끝날때까지 다른 커넥션이 해당 테이블에 접근하는 것을 막아주니까요.
일종의 Lock 인거죠.

확실치는 않아요.
그냥 확인하고 싶어서 댓글 남겨 봅니다.
비슷한 경험이 있으신 분 없으신지 궁금해서요.
전체 30 |RSS
그누보드5 팁자료실 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT