https://www.cnblogs.com/wodebudong/articles/7976474.html
최근 잠금 테이블의 경우가 발생 필드의 업데이트 문을 검색 할 경우, 인덱스, 작업의 대부분을 구축하지 않았다 찾을 수, 잠금 테이블의 경우가 있었다.
그래서 두 가지 질문이있다 :
-
인덱싱 및 인덱싱 잠금 테이블에 영향을주지 않습니다
-
일괄 업데이트는 테이블을 잠급니다 이유
1. 인덱스가 아닌 인덱스의 건설, 잠금 테이블에 미치는 영향
1. 2. 인덱스와 비는 인덱스
소개 전제 :
모드 : 명령 줄을 사용하여 시뮬레이션
트랜잭션이 자동 위탁 기본적으로 활성화되어 있으므로 우선 현재 데이터베이스가 열립니다 있는지 확인해야하기 때문에 자동으로 트랜잭션을 커밋 1.mysq.
명령 : @@ 자동 커밋을 선택;
결과는 다음과 같다 :
+ -------------- +
| @@ 자동 커밋 |
+ -------------- +
| 0 |
+ -------------- +
이 1 인 경우, 다음 명령을 실행 : 설정 자동 커밋 = 0; 자동 커밋을 사용하지 않도록 설정합니다
2. 현재 데이터베이스의 테이블 형식
tb_user | (표`tb_user`을 CREATE
`id` BIGINT (20) NOT NULL AUTO_INCREMENT,
`name`의 VARCHAR (32) DEFAULT의 NULL,
`phone`의 VARCHAR (11) DEFAULT의 NULL,
`operator`의 VARCHAR (32) DEFAULT의 NULL,
`gmt_create` 날짜의 DEFAULT NULL,
`gmt_modified` 날짜 DEFAULT의 NULL,
PRIMARY KEY (`id`)
) ENGINE = 이노 AUTO_INCREMENT = 3 = DEFAULT CHARSET UTF8
물론 기본 키 외에, 나는 어떤 인덱스를 추가하지 않았다
실제 예 :
1. 인덱스가 없습니다
시작, 열려있는 트랜잭션을, 다음 명령을 실행합니다 : 명령을 실행하여 업데이트 tb_user 세트 전화 = 11 이름 = "(C1)는"여기서, 수정, 먼저 트랜잭션을 커밋하지 않습니다.
창을 열려면 직접 명령을 실행 업데이트 tb_user 세트 전화 = 22 여기서 이름 = "C2"; 명령 붙어 찾을 수 있지만, 현재 측 트랜잭션이 잠금을 나타내는, 명령이 정상 작동 종료됩니다, 커밋 제출 테이블.
2. 인덱스 이름 필드를 부여
tb_user (이름)에 인덱스 INDEX_NAME을 만들;
제출하지 않도록, 이름 = "C1은"그럼 내부 작업으로 계속 그 사업을 열 수 있습니다 실행 갱신 tb_user 세트 전화 = (11)
그런 다음 다른 실행 업데이트 tb_user 세트는 전화 = 22 이름 = "C2"여기서, 검색 명령을 캐치하지 않았던는 잠금 테이블은 설명되지 않은
그러나, 또한 다른 tb_user 전화 세트를 업데이트하는 경우 = NAME = "C1"은 22, 로크 라인을 나타내는, 동일한 행을 업데이트
3. 요약
인덱스에 해당하는 SQL 문이하지 않은 경우 MySQL의 행 잠금은 즉, 잠금이 인덱스에 응답 행 라인에 적용되는 인덱스에 의해로드, 그것은 전체 테이블을 스캔
행 잠금이 테이블 잠금으로 대체 달성 할 수 없습니다.
한마디로 :이 경우 조건은 "잠금 테이블"업데이트 쿼리 업데이트를 사용하여 인덱스, 업데이트가 영향을 미치지 모든 행;
은 "라인 잠금"UDPATE에를 사용하여 인덱스의 추가 후, 오직 현재 행을 잠급니다. 업데이트 쿼리는 다른 라인에 영향을주지 않습니다.
2. 왜 일괄 업데이트가 테이블을 잠글
배치 갱신하기 때문에 테이블이 인덱싱되지 않기 때문에, 아주 느린 업데이트하기 위해 전체 테이블 리드를 검색하며, 트랜잭션을 커밋 SQL 각 업데이트는 트랜잭션이 전면 핸들의 잠금을 해제하는 트랜잭션의 제출 기다려야 후, 시간 제한이 있지만, 대기의 MySQL의 잠금 대기 시간보다 더 많은 예외가 테이블 잠금의 원인이 발생하는 경우 : 잠금 대기 제한 시간 초과, 트랜잭션을 다시 시작합니다
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'
innodb_lock_wait_timeout参数为超时时间的设置,默认为50,可以设大点,但并不能解决问题;所以加索引,或者优化代码;