답변:
거래를 사용하고 있습니다. autocommit은 트랜잭션을 비활성화하지 않고 명령문 끝에서 자동으로 커밋합니다.
일어나고있는 일이 있습니다. 다른 스레드가 일부 레코드에 대해 레코드 잠금을 유지하고 있습니다 (테이블의 모든 레코드를 업데이트 중입니다!). 스레드가 시간 초과되었습니다.
당신은 이벤트를 발행하여 이벤트에 대한 자세한 내용을 볼 수 있습니다
SHOW ENGINE INNODB STATUS
이벤트 후 ( sql
편집기에서). 이상적으로는 조용한 테스트 시스템에서이 작업을 수행하십시오.
process
유휴 상태 를 기다려야 합니다. 그렇다면이 오류가 발생할 수 있습니다. 내가 맞아?
connection.commit()
하는 사용자는 커밋 INSERT
하거나 UPDATE
방금 완료했습니다.
MySQL에서 잠긴 테이블의 잠금을 해제하는 방법 :
이와 같은 잠금을 해제 하면 데이터베이스의 원 자성 이 잠금 을 유발 한 SQL 문에 적용되지 않을 수 있습니다.
이것은 hackish이며 올바른 해결책은 잠금을 유발 한 응용 프로그램을 수정하는 것입니다. 그러나, 달러가 온라인에있을 때, 빠른 킥은 물건을 다시 움직일 것입니다.
1) MySQL 입력
mysql -u your_user -p
2) 잠긴 테이블 목록을 보자
mysql> show open tables where in_use>0;
3) 현재 프로세스 목록을 보자. 그 중 하나는 테이블을 잠그고 있습니다.
mysql> show processlist;
4)이 프로세스 중 하나를 종료
mysql> kill <put_process_id_here>;
mysql> set innodb_lock_wait_timeout=100
Query OK, 0 rows affected (0.02 sec)
mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100 |
+--------------------------+-------+
이제 잠금을 다시 트리거하십시오. SHOW ENGINE INNODB STATUS\G
데이터베이스에 a를 발행하는 데 100 초의 시간이 있으며 어떤 트랜잭션이 귀하를 잠그는 지 확인하십시오.
lock_wait_timeout
값
데이터베이스가 잘 조정되어 있는지 살펴보십시오. 특히 트랜잭션 격리. innodb_lock_wait_timeout 변수를 늘리는 것은 좋지 않습니다.
mysql cli에서 데이터베이스 트랜잭션 격리 레벨을 확인하십시오.
mysql> SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation, @@session.transaction_isolation;
+-----------------------+-----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation | @@session.tx_isolation |
+-----------------------+-----------------+------------------------+
| REPEATABLE-READ | REPEATABLE-READ | REPEATABLE-READ |
+-----------------------+-----------------+------------------------+
1 row in set (0.00 sec)
분리 레벨을 변경하여 개선을 얻을 수 있습니다. READ COMMITTED와 같은 오라클을 대신 반복 읽기 (InnoDB 기본값)로 사용하십시오.
mysql> SET tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)
mysql>
필요한 경우에만 SELECT FOR UPDATE를 사용하십시오.
tx_isolation
변수 이름이로 변경 되었습니다 transaction_isolation
.
제안 된 해결책 중 어느 것도 나를 위해 일하지 않았지만 이것은 효과가있었습니다.
쿼리 실행을 방해하는 것이 있습니다. 쿼리의 테이블 중 하나에서 다른 쿼리를 업데이트, 삽입 또는 삭제하는 경우가 많습니다. 그게 무엇인지 찾아야합니다.
SHOW PROCESSLIST;
차단 프로세스를 찾으면 해당 프로세스를 찾아서 id
실행하십시오.
KILL {id};
초기 쿼리를 다시 실행하십시오.
이 테이블 내의 다른 레코드를 업데이트 할 수 있습니까? 아니면이 테이블이 많이 사용됩니까? 내가 생각하고있는 것은 잠금을 얻으려고 시도하는 동안 설정된 시간 초과 가이 레코드를 업데이트해야한다는 것입니다. 도움이 될 수있는 시간을 늘릴 수 있습니다.
innodb_lock_wait_timeout
에서my.cnf
행 수가 많지 않습니다. 기본 키가 아닌 경우 account_import_id에 색인을 작성하십시오.
CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);
방금 큰 쿼리를 종료 한 경우 시간이 걸립니다 rollback
. 종료 된 조회가 롤백되기 전에 다른 조회를 발행하면 잠금 시간 종료 오류가 발생할 수 있습니다. 그것이 저에게 일어난 일입니다. 해결책은 조금만 기다려야했습니다.
세부:
약 1 백만 행 중 약 900,000을 제거하기 위해 DELETE 쿼리를 발행했습니다.
실수로 이것을 실행했습니다 (행의 10 % 만 제거).
DELETE FROM table WHERE MOD(id,10) = 0
이 대신 행의 90 %를 제거합니다.
DELETE FROM table WHERE MOD(id,10) != 0
10 %가 아닌 90 %의 행을 제거하고 싶었습니다. 그래서 지금까지 삭제 한 모든 행을 롤백한다는 것을 알고 MySQL 명령 줄에서 프로세스를 종료했습니다.
그런 다음 올바른 명령을 즉시 실행하고 lock timeout exceeded
곧 오류가 발생했습니다. 잠금은 실제로 rollback
백그라운드에서 여전히 종료 된 쿼리 의 잠금 일 수 있음을 깨달았습니다 . 그래서 몇 초 기다렸다가 쿼리를 다시 실행했습니다.
데이터베이스 테이블이 InnoDB 스토리지 엔진과 READ-COMMITTED 트랜잭션 격리 수준을 사용하고 있는지 확인하십시오.
SELECT @@ GLOBAL.tx_isolation, @@ tx_isolation로 확인할 수 있습니다. mysql 콘솔에서.
READ-COMMITTED로 설정되어 있지 않으면 설정해야합니다. mysql에 SUPER 권한이 있는지 설정하기 전에 확인하십시오.
http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html 에서 도움을받을 수 있습니다 .
이것을 설정하면 문제가 해결 될 것이라고 생각합니다.
두 프로세스에서 한 번에 업데이트하지 않으려는지 확인할 수도 있습니다. 이 컨텍스트에서 사용자 (@tala)와 비슷한 오류 메시지가 발생했습니다.
나는 Google에서 왔으며 나에게 맞는 솔루션을 추가하고 싶었습니다. 내 문제는 캐스케이드에 많은 FK가있는 거대한 테이블의 레코드를 삭제하려고했기 때문에 OP와 동일한 오류가 발생했습니다.
나는 비활성화하고 SQL 문장 끝에 autocommit
추가하면 효과가 COMMIT
있었습니다. 내가 이해하는 한 이것은 명령의 끝을 기다리는 대신 비트 단위로 버퍼를 해제합니다.
OP의 예를 유지하려면 다음과 같이 작동해야합니다.
mysql> set autocommit=0;
mysql> update customer set account_import_id = 1; commit;
autocommit
이전과 같이 MySQL 구성을 유지 하려면 다시 활성화하는 것을 잊지 마십시오 .
mysql> set autocommit=1;
내 경우에는 데이터를 수정하기 위해 비정상적인 쿼리를 실행하고있었습니다. 쿼리에서 테이블을 잠그면 잠금 시간 종료를 처리하지 않아도됩니다.
LOCK TABLES `customer` WRITE;
update customer set account_import_id = 1;
UNLOCK TABLES;
이것은 정상적인 사용에는 좋지 않습니다.
자세한 정보는 MySQL 8.0 참조 매뉴얼을 참조 하십시오.
나는 두 개의 Doctrine DBAL 연결을 가지고 있었는데, 그 중 하나는 비 트랜잭션 (중요한 로그의 경우)으로 서로 연결되지 않고 병렬로 실행됩니다.
CodeExecution(
TransactionConnectionQuery()
TransactionlessConnectionQuery()
)
통합 테스트는 테스트 후 데이터 롤백을 위해 트랜잭션으로 래핑되었습니다.
beginTransaction()
CodeExecution(
TransactionConnectionQuery()
TransactionlessConnectionQuery() // CONFLICT
)
rollBack()
내 솔루션은 해당 테스트에서 래핑 트랜잭션을 비활성화하고 다른 방법으로 db 데이터를 재설정하는 것이 었습니다.