mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.6 KiB
134 lines
4.6 KiB
#!/usr/bin/env python
|
|
"""
|
|
Kills all ProxySQL idle backend connections from a particular instance.
|
|
|
|
- Optional params (with default values): '{ "admin_host": "127.0.0.1", "admin_port": 6032, "admin_user": "radmin", "admin_pass": "radmin" }'
|
|
- Mandatory params: '{ "timeout": N }'
|
|
"""
|
|
|
|
import json
|
|
import jsonschema
|
|
import sys
|
|
import time
|
|
|
|
import pymysql.cursors
|
|
|
|
schema = {
|
|
"type": "object",
|
|
"properties": {
|
|
"admin_host": {"type": "string"},
|
|
"admin_port": {"type": "number"},
|
|
"admin_user": {"type": "string"},
|
|
"admin_pass": {"type": "string"},
|
|
"timeout": {"type": "number"}
|
|
},
|
|
"required": ["timeout"]
|
|
}
|
|
|
|
def validate_params():
|
|
"""Validates the JSON encoded received parameters."""
|
|
res = {}
|
|
|
|
if len(sys.argv) != 2:
|
|
res = {"err_code": 1, "res": "Invalid number of parameters"}
|
|
else:
|
|
try:
|
|
j_arg = json.loads(sys.argv[1])
|
|
jsonschema.validate(instance=j_arg, schema=schema)
|
|
|
|
res = {"err_code": 0, "res": ""}
|
|
except jsonschema.exceptions.ValidationError as err:
|
|
res = {"err_code": 1, "res": "Params validation failed: `" + str(err) + "`"}
|
|
except json.decoder.JSONDecodeError as err:
|
|
res = {"err_code": 1, "res": "Invalid supplied JSON: `" + str(err) + "`"}
|
|
|
|
return res
|
|
|
|
if __name__ == "__main__":
|
|
p_res = validate_params()
|
|
|
|
if p_res["err_code"] != 0:
|
|
print(json.dumps(p_res))
|
|
exit(0)
|
|
|
|
params = json.loads(sys.argv[1])
|
|
|
|
if params.get('admin_host') is None:
|
|
params['admin_host'] = "127.0.0.1"
|
|
if params.get('admin_port') is None:
|
|
params['admin_port'] = 6032
|
|
if params.get('admin_user') is None:
|
|
params['admin_user'] = "radmin"
|
|
if params.get('admin_pass') is None:
|
|
params['admin_pass'] = "radmin"
|
|
|
|
try:
|
|
proxy_admin_conn = pymysql.connect(
|
|
host=params['admin_host'],
|
|
user=params['admin_user'],
|
|
password=params['admin_pass'],
|
|
port=int(params['admin_port']),
|
|
cursorclass=pymysql.cursors.DictCursor,
|
|
defer_connect=True
|
|
)
|
|
|
|
proxy_admin_conn.client_flag |= pymysql.constants.CLIENT.MULTI_STATEMENTS
|
|
proxy_admin_conn.connect()
|
|
proxy_admin_conn.autocommit(True)
|
|
except Exception as err:
|
|
print(json.dumps({"err_code": 1, "res": "Connection attempt failed: `" + str(err) + "`"}))
|
|
exit(0)
|
|
|
|
with proxy_admin_conn:
|
|
with proxy_admin_conn.cursor() as cursor:
|
|
# Backup the current 'free_connections_pct'
|
|
prev_free_conns_pct = ""
|
|
|
|
s_var_query = "SELECT variable_value FROM global_variables WHERE variable_name='mysql-free_connections_pct'"
|
|
cursor.execute(s_var_query)
|
|
my_varval = cursor.fetchall()
|
|
|
|
if len(my_varval) != 1:
|
|
print(json.dumps({"err_code": 1, "res": "Invalid resulset received for query `" + s_var_query + "`"}))
|
|
exit(0)
|
|
else:
|
|
prev_free_conns_pct = my_varval[0]['variable_value']
|
|
|
|
# Set the 'free_connections_pct' to '0', to performa purge of the idle backend connections
|
|
update_query = "UPDATE global_variables SET variable_value=%s WHERE variable_name='mysql-free_connections_pct'"
|
|
cursor.execute(update_query, "0")
|
|
cursor.execute("LOAD MYSQL VARIABLES TO RUNTIME")
|
|
|
|
# Loop with a timeout until ProxySQL has cleaned all the backend connections
|
|
free_conns = -1
|
|
waited = 0
|
|
timeout = int(params['timeout'])
|
|
|
|
while free_conns != 0 and waited < timeout:
|
|
s_free_query = "SELECT SUM(ConnFree) FROM stats.stats_mysql_connection_pool"
|
|
|
|
cursor.execute(s_free_query)
|
|
my_rows = cursor.fetchall()
|
|
|
|
if len(my_rows) != 1:
|
|
print(json.dumps({"err_code": 1, "res": "Invalid resulset received for query `" + s_free_query + "`"}))
|
|
exit(0)
|
|
else:
|
|
conn_free_field = my_rows[0]['SUM(ConnFree)']
|
|
|
|
if conn_free_field is not None:
|
|
free_conns = int(conn_free_field)
|
|
else:
|
|
free_conns = 0
|
|
|
|
time.sleep(1)
|
|
|
|
# Recover previous 'mysql-free_connections_pct'
|
|
cursor.execute(update_query, prev_free_conns_pct)
|
|
cursor.execute("LOAD MYSQL VARIABLES TO RUNTIME")
|
|
|
|
if waited >= timeout:
|
|
print(json.dumps({"err_code": 1, "res": "Operation timedout"}))
|
|
else:
|
|
print(json.dumps({"err_code": 0, "res": "Success!"}))
|