I work on a data import application that updates a database. Data source is a bottleneck in my case therefore the data comes in chunks in multiple threads:
engine = create_engine(f"mysql+mysqldb://{DB_USER}:{DB_PASS}@{DB_HOST}/{DB_DB}")
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
def build_network():
...
for node_id in nodes:
thread = threading.Thread(
target=_build_page_nodes, args=(node_id, traversing_nodes, update),
name="Thread-" + node_id)
thread.start()
...
def _build_page_nodes(node_id, traversing_nodes, update):
session = Session()
...
logger.debug('Committing transaction')
session.commit()
Session.remove()
logger.debug('Done')
First thread executes fine. Next one however causes a problem. Here is a log of execution:
2021-05-05 09:52:02,846 INFO MainThread build_network 1 of 109015. 0 tasks are running
2021-05-05 09:52:04,811 DEBUG Thread-10000060 build_network Getting children for 10000060
2021-05-05 09:52:04,812 DEBUG Thread-10000060 build_network Committing transaction
2021-05-05 09:52:04,814 DEBUG Thread-10000060 build_network Done
2021-05-05 09:52:04,850 INFO MainThread build_network 2 of 109015. 0 tasks are running
2021-05-05 09:52:06,609 DEBUG Thread-10001280 build_network Getting children for 10001280
2021-05-05 09:52:06,610 DEBUG Thread-10001280 build_network Committing transaction
Exception in thread Thread-10001280:
Traceback (most recent call last):
File "/var/www/order/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1277, in _execute_context
self.dialect.do_execute(
File "/var/www/order/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 593, in do_execute
cursor.execute(statement, parameters)
File "/var/www/order/lib/python3.8/site-packages/MySQLdb/cursors.py", line 206, in execute
res = self._query(query)
File "/var/www/order/lib/python3.8/site-packages/MySQLdb/cursors.py", line 319, in _query
db.query(q)
File "/var/www/order/lib/python3.8/site-packages/MySQLdb/connections.py", line 259, in query
_mysql.connection.query(self, query)
MySQLdb._exceptions.OperationalError: (1205, 'Lock wait timeout exceeded; try restarting transaction')
The above exception was the direct cause of the following exception:
# Skipped the stacktrace
sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1205, 'Lock wait timeout exceeded; try restarting transaction')
[SQL: UPDATE network_nodes SET built_tree=%s WHERE network_nodes.id = %s]
[parameters: (1, '10001280')]
As I can see first thread is executed without problems. So I assumed it leaves some connection active. But as you can see I close and remove the session upon thread completion.
No other clients are using this database at the moment. Also when the application was single-threaded it ran ok. So is there something wrong with the way I finish the thread?