4 MySQL 트랩

7511 단어 sqldatabasemysqlrdbs

Originally posted at michaelzanggl.com. Subscribe to my newsletter to never miss out on new content.



참고: 이들 중 일부는 다른 데이터베이스 시스템에도 존재할 수 있습니다.

utf8은 실제로 utf8이 아닙니다.



이 SQL 예외가 발생한 적이 있습니까? Incorrect string value: ‘\xF0\x9F\x98\x83 <…’ for column...
당신은 아마도 다른 많은 사람들과 같은 함정에 빠졌을 것입니다. mySQL의 utf8 charset은 가능한 모든 유니코드 코드 포인트의 약 6%만 저장할 수 있습니다. 예를 들어 이모티콘도 제외됩니다.

insert into emails(body) values ('🦄🦄🦄');


그렇기 때문에 utf8mb4를 대신 사용해야 합니다.

자세한 내용 및 마이그레이션 방법: https://mathiasbynens.be/notes/mysql-utf8mb4

varchar_field를 false 또는 0과 비교



다음과 같은 고안된 예를 상상해보십시오.

function normalizeEmail(email) {
    if (!validate(email)) {
        return false
    }

    return normalize(email)
}

// somewhere in the code
await User.where('email', normalizeEmail(email)).first()


가상의 ORM은 쿼리를 실행합니다select * from users where email = <prepared value> LIMIT 1.
normalizeEmail 내부의 유효성 검사가 성공한 경우 쿼리는 select * from users where email = '[email protected]' LIMIT 1 가 됩니다.

유효성 검사가 성공하지 못한 경우 쿼리는 select * from users where email = false LIMIT 1 가 됩니다.

이제 데이터베이스 시스템에서 select * from users where <varchar field> = false와 같은 것을 실행하십시오.

필드가 비교할 수 없기 때문에 MySQL은 하나를 다른 것으로 변환하고 일치하게 만들고 모든 사용자를 반환합니다. 우리의 ORM은 단순히 첫 번째 사용자를 선택하고 그것으로 논리를 계속할 것입니다. 😬 꽤 위험하다.

The same happens with field = 0



중복 키 업데이트에 삽입하면 기본 키 구멍이 생성됩니다.


statistics (AI), id , fkid 열이 있는 테이블title이 있다고 상상해보십시오.

INSERT INTO statistics (fkid, title) VALUES (1, 'first');


이렇게 하면 id 1이 있는 새 레코드가 삽입됩니다. 항상 제목을 삽입하거나 업데이트하는 배치가 있다고 가정해 보겠습니다. 일정 시간 동안 다음 쿼리를 실행할 수 있습니다.

INSERT INTO statistics (fkid, title) VALUES (1, 'second') ON DUPLICATE KEY UPDATE title = 'second';
INSERT INTO statistics (fkid, title) VALUES (1, 'third') ON DUPLICATE KEY UPDATE title = 'third';
INSERT INTO statistics (fkid, title) VALUES (1, 'fourth') ON DUPLICATE KEY UPDATE title = 'fourth';


마지막으로 새 fkid가 있는 레코드를 삽입하려고 합니다.

INSERT INTO statistics (fkid, title) VALUES (100, 'first') ON DUPLICATE KEY UPDATE title = 'first';


이것은 테이블에 새 레코드를 삽입하지만 id가 무엇인지 추측합니까? 2가 될 것으로 예상할 수 있지만 실제로 insert on duplicate key updateupdate를 삽입하고 처리하는 데 실패할 때마다 내부적으로 자동 증분을 증가시켰습니다. 즉, 이 레코드의 id는 5가 됩니다.

ID가 실제로 순차적인 것은 그다지 중요하지 않지만 그 원인이 무엇인지 궁금할 수 있습니다.

자세히 알아보기: https://stackoverflow.com/questions/38347110/prevent-innodb-auto-increment-on-duplicate-key

int(2)는 당신이 생각하는 것과 다릅니다.



INT의 길이는 MySQL에서 실제 의미가 없습니다. 여전히 9999999와 같은 값을 삽입할 수 있습니다. 명령줄 클라이언트에 표시되어야 하는 문자 수만 제한합니다. 🤨

자세히 알아보기: https://stackoverflow.com/questions/5634104/what-is-the-size-of-column-of-int11-in-mysql-in-bytes

당신이 알고 있는 다른 함정이 있습니까?

좋은 웹페이지 즐겨찾기