N 초 후에 느린 MySQL 쿼리를 자동으로 종료하는 방법은 무엇입니까?


16

max_connection이 소진되는 것을 피하기 위해 잘 테스트 된 bash 스크립트 (또는 대안 솔루션)를 찾고 있습니다. 나는 그것이 증상과 싸우고 있다는 것을 알고 있지만 실제로는 단기 해결책과 같은 스크립트가 필요합니다.


어떤 버전의 MySQL을 사용하고 있습니까 ???
RolandoMySQLDBA 2016 년

MySQL 버전은 5.5입니다
alfish

답변:


21

percona 툴킷 에서 pt-kill 명령을 확인하십시오 .

- 그리고 .. 시스템 모니터링을 시작 할 munin , 선인장을 함께 더 나은 선인장 MySQL 용 템플릿 당신이 무슨 일이 일어나고 있는지 몇 가지 아이디어를 얻을 수 있도록, 아무것도. mysql 느린 쿼리를 로깅하는 것도 좋은 생각입니다.


제안에 대해 감사하지만 실제로 "일회용"스크립트를 찾으십시오.
alfish

5
pt-kill은 매우 잘 테스트되었으며 정확한 문제를 해결합니다. 명령 줄 매개 변수를 파악하고 실행하는 데 10 분 정도 걸립니다. 무엇을 더 원하십니까?
Aaron Brown

12

프로세스 목록이 INFORMATION_SCHEMA에있는 MySQL 5.1을 사용하는 경우 20 분 (1200 초)보다 오래 실행되는 쿼리에 대해 mysql 클라이언트 내에서 대량으로 KILL QUERY 명령을 생성 할 수 있습니다.

SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G

INFO 필드에 대해 WHERE 절을 수행하여 특정 쿼리, 장시간 실행되는 쿼리에 대한 TIME 필드 또는 특정 데이터베이스에 대한 DB 필드를 찾을 수 있습니다.

root @ localhost 인 경우 다음과 같이이를 실행할 수있는 모든 권한이 있어야합니다.

SECONDS_TOO_LONG=1200
KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword

이를 다음과 같이 crontab 할 수 있습니다.

SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
    KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
    mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
fi

다른 변형이 있습니다 :

SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
    KILLPROC_SQLSTMT="SELECT CONCAT('KILL QUERY ',id,';') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
    mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" > /tmp/kill_log_queries.sql
    mysql -uroot -ppassword < /tmp/kill_log_queries.sql
fi

BTW information_schema.processlist에서 정규화 된 테이블 이름으로 명시 적으로 읽었으므로 myDB를 지정하지 않았습니다.

다음은 당신이 볼 수있는 것의 데모입니다. 이 예제에서는 시간이 20000 초인 모든 프로세스의 KILL 명령을 에코합니다.

[root@***** ~]# mysql `lwdba_connect` -ANe"SELECT GROUP_CONCAT('KILL ',id,'; ' SEPARATOR ' ') FROM information_schema.processlist WHERE time > 25000 AND user<>'system user';"
+----------------------------------------------------+
| KILL 180186;  KILL 180141;  KILL 176419;  KILL 3;  |
+----------------------------------------------------+
[root@***** ~]#

나는 지난 5 년간이 기술을 사용해왔다. 사실, 나는 작년에이 답변을 DBA StackExchange에 제출했고 받아 들여 졌습니다.


롤랜드, 당신은 이것을 명확히 할 수 있습니까?이 명령이 지속적입니까, 아니면 자주 실행해야합니까? mysql 사용자가 'root'이고 데이터베이스 이름이 myDB라고 가정하면 명령에서 무엇을 대체해야합니까? 감사합니다
alfish 2016 년

내 답변을 업데이트했습니다.
RolandoMySQLDBA 2016 년

고맙지 만 마지막 레시피를 bash 스크립트로 바꾸면 1 줄에 ERROR 1064 (42000)이 표시됩니다. SQL 구문에 오류가 있습니다. 1 번 라인의 ''near
alfish

어떤 SQL 명령이 해당 오류를 생성 했습니까 ???
RolandoMySQLDBA

롤랜드 SF는 샌드 박스가 아닙니다. 솔루션으로 무언가를 제안하기 전에 테스트하는 것이 좋습니다. 또한 모든 연결이 포화 상태 일 때 mysql은 결함이 없다고 가정하여 어떻게 프로 시저를 실행합니까?
alfish 2016 년

6

나는이 다음 코드 냈다 발견 여기에 :

2013-01-14 업데이트 : 잠재적으로 위험하며 복제 프로세스를 중단시킬 수 있다는 익명의 힌트가있었습니다. 따라서 귀하의 책임하에 사용하십시오 :

mysql -e 'show processlist\G' |\
egrep -b5 'Time: [0-9]{2,}' |\
grep 'Id:' |\
cut -d':' -f2 |\
sed 's/^ //' |\
while read id
do
  mysql -e "kill $id;"
done

위의 스 니펫에서 시간 상수는 얼마입니까?
alfish 2016 년

@alfish 나는 저자가 아니지만 적어도 두 자리 숫자가있는 모든 시간 값과 일치하는 정규 표현식이라고 말하고 싶습니다. 여기에서 10은 너무 길다고 가정합니다.
Nils

1

MySQL 5.7 이후에는 max_execution_time 변수를 사용하여 모든 "SELECT"읽기 쿼리에 대해이 작업을 자동으로 수행 할 수 있습니다.


0

가동 시간이 마음에 들면 bash 솔루션을 시도하지 않을 것입니다!

코드에 액세스 할 수있는 경우 여기에 설명 된 방법을 사용하여 실제로 SELECT 문에서 최대 실행 시간을 설정할 수 있습니다 .

SELECT 
MAX_EXECUTION_TIME = 1000 --in milliseconds
* 
FROM table;

그렇지 않으면 서버에서 :

/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query

pt-kill 설치 :

$ wget percona.com/get/pt-kill

프로세스리스트의 스냅 샷을 작성하십시오.

$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt

스냅 샷에서 pt-kill을 테스트하십시오.

$ ./pt-kill --test-matching processlist.txt --busy-time 45 --kill-busy-commands 'Execute' --victims all --print
# 2019-02-25T17:34:37 KILL 45710302 (Execute 374 sec) SELECT\n\tCOUNT(DISTINCT(LP.sessionId))\nFROM lp_traffic LP\nINNER JOIN orders O ON O.orderId = LP.order
# 2019-02-25T17:34:37 KILL 45713515 (Execute 67 sec) SELECT \n\tCOUNT(DISTINCT(CASE WHEN T.response = 'SUCCESS' AND T.isVoid = 0 AND (T.txnType IN

일치 규칙이 귀하의 상황에 맞는지 확인하십시오. 위의 내용은 45 초 동안 모든 Execute 문을 종료시킵니다. 확신이 있으면이 명령을 수정하고 실행하여 10 초 간격으로 명령문을 실행하십시오.

$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.