MySQL 암시적 유형 변환 트랩 및 규칙_MySQL
머리말
암시적 유형 변환이 색인에 도달하지 못할 위험이 있다는 것은 모두가 알고 있다고 생각합니다. 동시성이 높고 데이터 양이 많은 경우 색인 누락으로 인한 결과가 매우 심각합니다. 데이터베이스가 질질 끌리고 시스템 전체가 붕괴되어 대규모 시스템에 막대한 손실을 초래하게 됩니다. 그럼 이번 글을 통해 MySQL 암시적 유형 변환 트랩과 규칙에 대해 알아보겠습니다.
1. 암시적 유형 변환 예시
오늘 프로덕션 데이터베이스에 갑자기 MySQL 스레드 수 알람이 나타났고, IOPS가 매우 높았으며, 인스턴스 세션에 다음과 유사한 SQL이 많이 나타났습니다. (관련 필드 및 값이 수정되었습니다.)
SELECT f_col3_id,f_qq1_id FROM d_dbname.t_tb1 WHERE f_col1_id=1226391 and f_col2_id=1244378 and f_qq1_id in (12345,23456,34567,45678,56789,67890,78901,89012,90123,901231,901232,901233)
설명을 사용하여 스캔된 행 수와 인덱스 선택을 확인하세요.
mysql>explain SELECT f_col3_id,f_qq1_id FROM d_dbname.t_tb1 WHERE f_col1_id=1226391 and f_col2_id=1244378 and f_qq1_id in (12345,23456,34567,45678,56789,67890,78901,89012,90123,901231,901232,901233); +------+---------------+---------+--------+--------------------------------+---------------+------------+--------+--------+------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+---------------+---------+--------+--------------------------------+---------------+------------+--------+--------+------------------------------------+ | 1 | SIMPLE | t_tb1 | ref | uid_type_frid,idx_corpid_qq1id | uid_type_frid | 8 | const | 1386 | Using index condition; Using where | +------+---------------+---------+--------+--------------------------------+---------------+------------+--------+--------+------------------------------------+ 共返回 1 行记录,花费 11.52 ms.
t_tb1 테이블에는 uid_type_frid(f_col2_id,f_type)
, idx_corp_id_qq1id(f_col1_id,f_qq1_id)
인덱스가 있는데 후자를 선택하면 f_qq1_id
의 필터링 효과가 매우 좋을텐데 전자를 선택하게 된다. hint use index(idx_corp_id_qq1id)
사용 시:
mysql>explain extended SELECT f_col3_id,f_qq1_id FROM d_dbname.t_tb1 use index(idx_corpid_qq1id) WHERE f_col1_id=1226391 and f_col2_id=1244378 and f_qq1_id in (12345,23456,34567,45678,56789,67890,78901,89012,90123,901231,901232,901233); +------+---------------+--------+--------+---------------------+------------------+------------+----------+-------------+------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+---------------+--------+--------+---------------------+------------------+------------+----------+-------------+------------------------------------+ | 1 | SIMPLE | t_tb1 | ref | idx_corpid_qq1id | idx_corpid_qq1id | 8 | const | 2375752 | Using index condition; Using where | +---- -+---------------+--------+--------+---------------------+------------------+------------+----------+-------------+------------------------------------+ 共返回 1 行记录,花费 17.48 ms. mysql>show warnings; +-----------------+----------------+-----------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-----------------+----------------+-----------------------------------------------------------------------------------------------------------------------+ | Warning | 1739 | Cannot use range access on index 'idx_corpid_qq1id' due to type or collation conversion on field 'f_qq1_id' | | Note | 1003 | /* select#1 */ select `d_dbname`.`t_tb1`.`f_col3_id` AS `f_col3_id`,`d_dbname`.`t_tb1`.`f_qq1_id` AS `f_qq1_id` from `d_dbname`.`t_tb1` USE INDEX (`idx_corpid_qq1id`) where | | | | ((`d_dbname`.`t_tb1`.`f_col2_id` = 1244378) and (`d_dbname`.`t_tb1`.`f_col1_id` = 1226391) and (`d_dbname`.`t_tb1`.`f_qq1_id` in | | | | (12345,23456,34567,45678,56789,67890,78901,89012,90123,901231,901232,901233))) | +-----------------+----------------+-----------------------------------------------------------------------------------------------------------------------+ 共返回 2 行记录,花费 10.81 ms.
행 열이 200만 행에 도달했지만 문제도 발견되었습니다. select_type
은 range
이어야 하고 key_len
은 idx_corpid_qq1id
인덱스의 첫 번째 열만 사용된 것을 확인했습니다. 위의 설명은 extended
을 사용하므로 경고를 표시하면 f_qq1_id
에 암시적 유형 변환이 있음을 명확하게 알 수 있습니다. f_qq1_id
은 varchar
이고 후속 비교 값은 정수입니다.
이 문제에 대한 해결책은 암시적 유형 변환으로 인한 제어 불가능성을 피하는 것입니다. f_qq1_id in
의 내용을 문자열로 작성합니다:
mysql>explain SELECT f_col3_id,f_qq1_id FROM d_dbname.t_tb1 WHERE f_col1_id=1226391 and f_col2_id=1244378 and f_qq1_id in ('12345','23456','34567','45678','56789','67890','78901','89012','90123','901231'); +-------+---------------+--------+---------+--------------------------------+------------------+-------------+---------+---------+------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------+---------------+--------+---------+--------------------------------+------------------+-------------+---------+---------+------------------------------------+ | 1 | SIMPLE | t_tb1 | range | uid_type_frid,idx_corpid_qq1id | idx_corpid_qq1id | 70 | | 40 | Using index condition; Using where | +-------+---------------+--------+---------+--------------------------------+------------------+-------------+---------+---------+------------------------------------+ 共返回 1 行记录,花费 12.41 ms.
스캔 줄 수가 1386줄에서 40줄로 줄었습니다.
비슷한 경우도 있습니다.
SELECT count(0) FROM d_dbname.t_tb2 where f_col1_id= '1931231' AND f_phone in(098890); | Warning | 1292 | Truncated incorrect DOUBLE value: '1512-98464356'
최적화 후 스캔된 행이 100만 행에서 1개로 직접 줄었습니다.
이 기회에 mysql의 암시적 유형 변환을 체계적으로 살펴보세요.
2. mysql 암시적 변환 규칙
2.1 규칙
암시적 변환 규칙을 분석해 보겠습니다.
a. 두 매개변수 중 하나 이상이 NULL
인 경우 비교 결과도 NULL
입니다. 단, <=>를 사용하여 두 개의 NULL
을 비교할 경우에는 1이 반환됩니다. 이 두 경우에는 유형 변환이 필요하지 않습니다
b. 두 매개변수 모두 문자열이며 유형 변환 없이 문자열에 따라 비교됩니다.
c. 두 매개변수는 모두 정수이며 유형 변환 없이 정수로 비교됩니다.
d. 16진수 값을 숫자가 아닌 값과 비교할 경우 2진수 문자열로 처리됩니다
e. 한 매개변수가 TIMESTAMP
또는 DATETIME
이고 다른 매개변수가 상수인 경우 상수는 timestamp
로 변환됩니다.
f. 한 매개변수가 decimal
유형입니다. 다른 매개변수가 decimal
또는 정수이면 비교를 위해 정수가 decimal
로 변환됩니다. decimal
비교를 위해 부동소수점 숫자로 변환
으로 변환됩니다.
g. 다른 모든 경우에는 비교 전에 두 매개변수가 모두 부동 소수점 숫자로 변환됩니다.
mysql> select 11 + '11', 11 + 'aa', 'a1' + 'bb', 11 + '0.01a'; +-----------+-----------+-------------+--------------+ | 11 + '11' | 11 + 'aa' | 'a1' + 'bb' | 11 + '0.01a' | +-----------+-----------+-------------+--------------+ | 22 | 11 | 0 | 11.01 | +-----------+-----------+-------------+--------------+ 1 row in set, 4 warnings (0.00 sec) mysql> show warnings; +---------+------+-------------------------------------------+ | Level | Code | Message | +---------+------+-------------------------------------------+ | Warning | 1292 | Truncated incorrect DOUBLE value: 'aa' | | Warning | 1292 | Truncated incorrect DOUBLE value: 'a1' | | Warning | 1292 | Truncated incorrect DOUBLE value: 'bb' | | Warning | 1292 | Truncated incorrect DOUBLE value: '0.01a' | +---------+------+-------------------------------------------+ 4 rows in set (0.00 sec) mysql> select '11a' = 11, '11.0' = 11, '11.0' = '11', NULL = 1; +------------+-------------+---------------+----------+ | '11a' = 11 | '11.0' = 11 | '11.0' = '11' | NULL = 1 | +------------+-------------+---------------+----------+ | 1 | 1 | 0 | NULL | +------------+-------------+---------------+----------+ 1 row in set, 1 warning (0.01 sec)
위에서 볼 수 있듯이 11 + 'aa'는 연산자의 양쪽 유형이 다르고 조항 G를 따르기 때문에 aa를 부동 소수점 소수점으로 변환해야 하지만 변환이 실패합니다. (문자는 잘림) 0으로 변환된다고 볼 수 있는데, 정수 11은 부동소수점형이나 그 자체로 변환되므로 11 + 'aa' = 11이다.
0.01a를 double
형으로 변환하면 역시 0.01로 잘려지므로 11 + '0.01a' = 11.01이 됩니다.
동등 비교도 이 점을 보여줍니다. 변환 후 '11a'와 '11.0'은 모두 11입니다. 이것이 기사 시작 부분의 예가 색인화되지 않은 이유입니다. varchar
유형 f_qq1_id
. 부동 소수점 유형을 비교할 때 12345a, 12345.b 등 12345와 같은 상황이 셀 수 없이 많습니다. MySQL 옵티마이저는 인덱스가 더 효과적인지 여부를 판단할 수 없으므로 다른 솔루션을 선택합니다.
그러나 암시적 유형 변환이 발생하는 한 위와 유사한 성능 문제가 발생하게 됩니다. 결국 변환 후 인덱스를 효과적으로 선택할 수 있는지 여부에 달려 있습니다. f_id = '654321'
, f_mtime between '2016-05-01 00:00:00'
, '2016-05-04 23:59:59'
과 마찬가지로 앞의 f_id가 정수이기 때문에 인덱스 선택에 영향을 미치지 않습니다. double로 변환된 후속 문자열 유형 숫자와 비교하더라도 f_id의 값은 여전히 될 수 있습니다. double을 기준으로 결정되며 인덱스는 여전히 효율적입니다. 후자는 e항에 따르지만 오른쪽의 상수가 변환되었기 때문이다.
개발자는 이러한 암시적 유형 변환의 함정에 빠질 수 있지만 이에 대해 주의를 기울이지 않는 경우가 많기 때문에 많은 규칙을 기억할 필요가 없으며 유형과 유형을 비교하기만 하면 됩니다.
2.2 암시적 유형 변환의 보안 문제
암시적 유형 변환은 성능 문제뿐만 아니라 보안 문제도 일으킬 수 있습니다.
mysql> desc t_account; +-----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+-------------+------+-----+---------+----------------+ | fid | int(11) | NO | PRI | NULL | auto_increment | | fname | varchar(20) | YES | | NULL | | | fpassword | varchar(50) | YES | | NULL | | +-----------+-------------+------+-----+---------+----------------+ mysql> select * from t_account; +-----+-----------+-------------+ | fid | fname | fpassword | +-----+-----------+-------------+ | 1 | xiaoming | p_xiaoming | | 2 | xiaoming1 | p_xiaoming1 | +-----+-----------+-------------+
假如应用前端没有WAF防护,那么下面的sql很容易注入:
mysql> select * from t_account where fname='A' ; fname传入 A' OR 1='1 mysql> select * from t_account where fname='A' OR 1='1';
攻击者更聪明一点: fname
传入 A'+'B ,fpassword
传入 ccc'+0 :
mysql> select * from t_account where fname='A'+'B' and fpassword='ccc'+0; +-----+-----------+-------------+ | fid | fname | fpassword | +-----+-----------+-------------+ | 1 | xiaoming | p_xiaoming | | 2 | xiaoming1 | p_xiaoming1 | +-----+-----------+-------------+ 2 rows in set, 7 warnings (0.00 sec)
总结
以上就是为大家总结的MySQL隐式类型的转换陷阱和规则,希望这篇文章对大家学习或者mysql能有所帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











전체 테이블 스캔은 MySQL에서 인덱스를 사용하는 것보다 빠를 수 있습니다. 특정 사례는 다음과 같습니다. 1) 데이터 볼륨은 작습니다. 2) 쿼리가 많은 양의 데이터를 반환 할 때; 3) 인덱스 열이 매우 선택적이지 않은 경우; 4) 복잡한 쿼리시. 쿼리 계획을 분석하고 인덱스 최적화, 과도한 인덱스를 피하고 정기적으로 테이블을 유지 관리하면 실제 응용 프로그램에서 최상의 선택을 할 수 있습니다.

InnoDB의 전체 텍스트 검색 기능은 매우 강력하여 데이터베이스 쿼리 효율성과 대량의 텍스트 데이터를 처리 할 수있는 능력을 크게 향상시킬 수 있습니다. 1) InnoDB는 기본 및 고급 검색 쿼리를 지원하는 역 색인화를 통해 전체 텍스트 검색을 구현합니다. 2) 매치 및 키워드를 사용하여 검색, 부울 모드 및 문구 검색을 지원합니다. 3) 최적화 방법에는 워드 세분화 기술 사용, 인덱스의 주기적 재건 및 캐시 크기 조정, 성능과 정확도를 향상시키는 것이 포함됩니다.

예, MySQL은 Windows 7에 설치 될 수 있으며 Microsoft는 Windows 7 지원을 중단했지만 MySQL은 여전히 호환됩니다. 그러나 설치 프로세스 중에 다음 지점이 표시되어야합니다. Windows 용 MySQL 설치 프로그램을 다운로드하십시오. MySQL의 적절한 버전 (커뮤니티 또는 기업)을 선택하십시오. 설치 프로세스 중에 적절한 설치 디렉토리 및 문자를 선택하십시오. 루트 사용자 비밀번호를 설정하고 올바르게 유지하십시오. 테스트를 위해 데이터베이스에 연결하십시오. Windows 7의 호환성 및 보안 문제에 주목하고 지원되는 운영 체제로 업그레이드하는 것이 좋습니다.

MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 1) 데이터베이스 및 테이블 작성 : CreateAbase 및 CreateTable 명령을 사용하십시오. 2) 기본 작업 : 삽입, 업데이트, 삭제 및 선택. 3) 고급 운영 : 가입, 하위 쿼리 및 거래 처리. 4) 디버깅 기술 : 확인, 데이터 유형 및 권한을 확인하십시오. 5) 최적화 제안 : 인덱스 사용, 선택을 피하고 거래를 사용하십시오.

클러스터 인덱스와 비 클러스터 인덱스의 차이점은 1. 클러스터 된 인덱스는 인덱스 구조에 데이터 행을 저장하며, 이는 기본 키 및 범위별로 쿼리에 적합합니다. 2. 클러스터되지 않은 인덱스는 인덱스 키 값과 포인터를 데이터 행으로 저장하며 비 예산 키 열 쿼리에 적합합니다.

MySQL 및 MariaDB는 공존 할 수 있지만주의해서 구성해야합니다. 열쇠는 각 데이터베이스에 다른 포트 번호와 데이터 디렉토리를 할당하고 메모리 할당 및 캐시 크기와 같은 매개 변수를 조정하는 것입니다. 연결 풀링, 애플리케이션 구성 및 버전 차이도 고려해야하며 함정을 피하기 위해 신중하게 테스트하고 계획해야합니다. 두 개의 데이터베이스를 동시에 실행하면 리소스가 제한되는 상황에서 성능 문제가 발생할 수 있습니다.

MySQL 데이터베이스에서 사용자와 데이터베이스 간의 관계는 권한과 테이블로 정의됩니다. 사용자는 데이터베이스에 액세스 할 수있는 사용자 이름과 비밀번호가 있습니다. 권한은 보조금 명령을 통해 부여되며 테이블은 Create Table 명령에 의해 생성됩니다. 사용자와 데이터베이스 간의 관계를 설정하려면 데이터베이스를 작성하고 사용자를 생성 한 다음 권한을 부여해야합니다.

MySQL은 B-Tree, Hash, Full-Text 및 Spatial의 4 가지 인덱스 유형을 지원합니다. 1.B- 트리 색인은 동일한 값 검색, 범위 쿼리 및 정렬에 적합합니다. 2. 해시 인덱스는 동일한 값 검색에 적합하지만 범위 쿼리 및 정렬을 지원하지 않습니다. 3. 전체 텍스트 색인은 전체 텍스트 검색에 사용되며 다량의 텍스트 데이터를 처리하는 데 적합합니다. 4. 공간 지수는 지리 공간 데이터 쿼리에 사용되며 GIS 응용 프로그램에 적합합니다.
