Blog
October 9, 2015 Marie H.

Fixing SQLAlchemy MySQL Errors on UWSGI Restart

Fixing SQLAlchemy MySQL Errors on UWSGI Restart

I’ve been building a Python Flask RESTful API during the day and recently came across problem that anytime I would restart UWSGI which is serving my Flask App the first 5 connections to MySQL would fail and then magically they would work.

This is because by default UWSGI loads your app once in a parent thread and then forks() for each child thread. So I had 5 workers and I’m guessing that UWSGI just round robins through each thread so what was happening was that the connection to MySQL through SQLAlchemy was being dropped and recreated in each child thread of UWSGI. This lead to mass frustration where I first started debugging MySQL and not my application.

Fortunately, there is an easy fix for this. In your UWSGI ini file all you need to do is add:

lazy-apps = true

Or for those running via cli throw the flag: –lazy-apps

It is important to note that this option will increase your memory footprint as you are loading your application for each worker. However it does resolve the following type of errors on restart:

(_mysql_exceptions.ProgrammingError) (2014, "Commands out of sync; you can't run this command now") [SQL: u'SELECT account.id AS account_id, account.email AS account_email, account.password_hash AS account_password_hash, account.first_name AS account_first_name, account.last_name AS account_last_name, account.phone_number AS account_phone_number, account.company_name AS account_company_name, account.role AS account_role, account.created AS account_created, account.updated AS account_updated \nFROM account \nWHERE account.id = %s \n LIMIT %s'] [parameters: (1, 1)]
[pid: 6354|app: 0|req: 2/5] 71.41.191.106 () {44 vars in 841 bytes} [Fri Oct  9 13:42:12 2015] GET /api/account/read => generated 0 bytes in 31 msecs (HTTP/1.1 500) 0 headers in 0 bytes (1 switches on core 0)
context)
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2013, 'Lost connection to MySQL server during query') [SQL: u'SELECT notification_settings.id AS notification_settings_id, notification_settings.account_id AS notification_settings_account_id, notification_settings.email_critical AS notification_settings_email_critical, notification_settings.email_warning AS notification_settings_email_warning, notification_settings.email_all AS notification_settings_email_all, notification_settings.sms_critical AS notification_settings_sms_critical, notification_settings.sms_warning AS notification_settings_sms_warning, notification_settings.sms_all AS notification_settings_sms_all, notification_settings.sms_number AS notification_settings_sms_number \nFROM notification_settings \nWHERE notification_settings.account_id = %s \n LIMIT %s'] [parameters: (1, 1)]
[pid: 6355|app: 0|req: 1/6] 71.41.191.106 () {44 vars in 887 bytes} [Fri Oct  9 13:42:12 2015] GET /api/account/settings/notifications/read => generated 0 bytes in 29 msecs (HTTP/1.1 500) 0 headers in 0 bytes (1 switches on core 0)
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2006, 'MySQL server has gone away') [SQL: u'SELECT account.id AS account_id, account.email AS account_email, account.password_hash AS account_password_hash, account.first_name AS account_first_name, account.last_name AS account_last_name, account.phone_number AS account_phone_number, account.company_name AS account_company_name, account.role AS account_role, account.created AS account_created, account.updated AS account_updated \nFROM account \nWHERE account.id = %s \n LIMIT %s'] [parameters: (1, 1)]
[pid: 6353|app: 0|req: 1/9] 71.41.191.106 () {44 vars in 841 bytes} [Fri Oct  9 13:42:15 2015] GET /api/account/read => generated 0 bytes in 18 msecs (HTTP/1.1 500) 0 headers in 0 bytes (1 switches on core 0)
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2006, 'MySQL server has gone away') [SQL: u'SELECT notification_settings.id AS notification_settings_id, notification_settings.account_id AS notification_settings_account_id, notification_settings.email_critical AS notification_settings_email_critical, notification_settings.email_warning AS notification_settings_email_warning, notification_settings.email_all AS notification_settings_email_all, notification_settings.sms_critical AS notification_settings_sms_critical, notification_settings.sms_warning AS notification_settings_sms_warning, notification_settings.sms_all AS notification_settings_sms_all, notification_settings.sms_number AS notification_settings_sms_number \nFROM notification_settings \nWHERE notification_settings.account_id = %s \n LIMIT %s'] [parameters: (1, 1)]
[pid: 6351|app: 0|req: 5/12] 71.41.191.106 () {44 vars in 887 bytes} [Fri Oct  9 13:42:19 2015] GET /api/account/settings/notifications/read => generated 0 bytes in 19 msecs (HTTP/1.1 500) 0 headers in 0 bytes (1 switches on core 0)

So far I have not seen any performance degradation to implementing lazy-apps via UWSGI but it is definitely a lot less frustrating having my app work as expected.