Lost connection between Python program and MySQL

Question:

Why do I get this error?

Mysql.connector.errors.DatabaseError: 2003 (HY000): Can’t connect to MySQL server n ‘3.XX.XXX.89’ (110)

I am collecting data from MQTT broker and storing it in a MySQL database. For subscribing to the topics on MQTT broker, I am using Paho MQTT client and for connecting to the MySQL database server, I am using MySQL python connector.
I run this python script in the background continuously on Amazon EC2 Ubuntu instance (Virtual Server):

import mysql.connector
import paho.mqtt.client as mqtt

#Mysql Settings
db = mysql.connector.connect(host='localhost',
                     user='user_name',
                     password='password',
                     db='db_name')

if db.is_connected():
   db_Info = db.get_server_info()
   print("Connected to MySQL Server version ", db_Info)

cursor = db.cursor()

#MQTT Settings
MQTT_Broker = "3.XX.XXX.89"
MQTT_Port = 1883
Keep_Alive_Interval = 60
MQTT_Topic = "my/publish/#"

#Subscribe
def on_connect(client, userdata, flags, rc):
    mqttc.subscribe(MQTT_Topic, 0)
    print("subscribed")

#Save data into DB Table
def on_message(mosq, obj, msg):
    print("Insert from MQTT")
    print("wait")
    print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
    sql = """INSERT INTO gnss (topic, gnssdata) VALUES (%s,%s)"""
    tuple = (msg.topic, msg.payload)
    cursor.execute(sql, tuple)
    db.commit()
    print("Record inserted successfully into gnss table")


def on_subscribe(mosq, obj, mid, granted_qos):
    pass

mqttc = mqtt.Client()

#Assign Event Callbacks
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_subscribe = on_subscribe

#Connect
mqttc.connect(MQTT_Broker, int(MQTT_Port), int(Keep_Alive_Interval))

#Continue the network loop and close db connection
mqttc.loop_forever()
db.close()
print("MySQL connection is closed")

Mosquitto for mqtt and mysql server are installed on this virtual server.
First when I run this script, all data from MQTT broker is collected and stored into the mysql database. It worked properly for the whole day. The next day without doing any changes, i sent data to the MQTT broker. The data was collected by the paho mqtt client but it was not able to store this data in the mysql database.
The error and output is as follows:

('Connected to MySQL Server version ', '5.7.30-0ubuntu0.18.04.1')
subscribed
Insert from MQTT
wait
my/publish/topic 0 acc, 10245, tyu
Record inserted successfully into gnss table
Insert from MQTT
wait
my/publish/topic 0 hello world
Record inserted successfully into gnss table
Insert from MQTT
wait
my/publish/topic 0 hello world
Record inserted successfully into gnss table
Insert from MQTT
wait
my/publish/topic 0 new test
Record inserted successfully into gnss table
Insert from MQTT
wait
my/publish/topic 0 19/05/2020
Insert from MQTT
wait
my/publish/topic 0 19/05/2020
Insert from MQTT
wait
my/publish/topic 0 Tuesday
Insert from MQTT
wait
my/publish/topic 0 Tuesday
Traceback (most recent call last):
  File "mqtt.py", line 8, in <module>
    db='nrf91')
  File "/home/ubuntu/.local/lib/python2.7/site-packages/mysql/connector/__init__.py", line 264, in connect
    return CMySQLConnection(*args, **kwargs)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/mysql/connector/connection_cext.py", line 80, in __init__
    self.connect(**kwargs)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/mysql/connector/abstracts.py", line 960, in connect
    self._open_connection()
  File "/home/ubuntu/.local/lib/python2.7/site-packages/mysql/connector/connection_cext.py", line 219, in _open_connection
    sqlstate=exc.sqlstate)
mysql.connector.errors.DatabaseError: 2003 (HY000): Can't connect to MySQL server on '3.XX.XXX.89' (110)

I am getting this mysql connector database error. How to solve this error? Initialy there is connection to the mysql server but the next day it is gone. So how to keep it connected to the mysql server for the whole time without causing this error?

Asked By: Jagruti Kapgate

||

Answers:

Connections between clients (like your python program) and MySQL don’t stay open forever when they’re not in use. MySQL drops connections when its wait_timeout, or interactive_timeout, expires.

It sounds like your program works all day and sleeps all night (like the lumberjack in the Monty Python schtick). When it wakes up it has no connection to the database because MySQL closed it.

What can you do about this? In my order of preference:

  1. Change your program to use a connection pool. If you do that the pooling logic will restore a connection when you need it.

  2. Right before your program handles each queued item, perform a no-op operation like SELECT 1;. If that operation throws an exception, reopen the database connection. This is a good solution because it makes your application more resilient if the MySQL database server must be restarted. Sometimes cloud providers (AWS, Azure, Digital Ocean, others) have to take host machines out of service. When they do that they bounce customer virtual machines so they can start on new host machines. If you’re lucky they warn you first.

  3. Update your program so it closes its database connection when its queue of work becomes empty, and reopens it when it has work to do.

  4. Once every so often (a minute?) do a no-op SELECT 1; as a keepalive so MySQL won’t close the connection.

  5. Change the wait_timeout value to something long enough. This sets it to one week.

SET @@GLOBAL.wait_timeout=604800

Use 86400 for one day.

Knowing how to set the timeout is also useful because it lets you test your solution to this problem without waiting a long time.

Answered By: O. Jones