in core/lib/payload/copy.py [0:0]
def lock_tables(self, tables):
for _ in range(self.lock_max_attempts):
# We use a threading.Timer with a second connection in order to
# kill any selects on top of the tables being altered if we could
# not lock the tables in time
another_conn = self.get_conn(self._current_db)
kill_timer = Timer(
self.lock_max_wait_before_kill_seconds,
self.kill_selects,
args=(tables, another_conn),
)
# keeping a reference to kill timer helps on tests
self._last_kill_timer = kill_timer
kill_timer.start()
try:
self.execute_sql(sql.lock_tables(tables))
# It is best to cancel the timer as soon as possible
kill_timer.cancel()
log.info(
"Successfully lock table(s) for write: {}".format(", ".join(tables))
)
break
except MySQLdb.MySQLError as e:
errcode, errmsg = e.args
# 1205 is timeout and 1213 is deadlock
if errcode in (1205, 1213):
log.warning("Retry locking because of error: {}".format(e))
else:
raise
finally:
# guarantee that we dont leave a stray kill timer running
# or any open resources
kill_timer.cancel()
kill_timer.join()
another_conn.close()
else:
# Cannot lock write after max lock attempts
raise OSCError("FAILED_TO_LOCK_TABLE", {"tables": ", ".join(tables)})