error while updating table in MySQL : mysql.connector.errors.DatabaseError: 1412 (HY000): Table definition has changed, please retry transaction

huangapple go评论54阅读模式
英文:

error while updating table in MySQL : mysql.connector.errors.DatabaseError: 1412 (HY000): Table definition has changed, please retry transaction

问题

I am working on one personal project.
There is multiple similar questions on this forum however everyone is case specific.
In my case i am creating and loading temp table, i am joining that table with existing table in DB and updating the same table based on temp table results. while executing db.execute_insert_update() it throws an exception : mysql.connector.errors.DatabaseError: 1412 (HY000): Table definition has changed, please retry transaction

 >  def _create_and_load_table(self, dataframe: DataFrame) -> str: #first_function
    self._log_entry()
    temp_table_name = self._generate_table_name()
    table_schema = "partner_staging"
    table_with_schema = f"{table_schema}.{temp_table_name}"

    self.df_mgr.jdbc_write(dataframe=dataframe, dbtable=table_with_schema, 
   check_count_before_write=True)
    self._log_exit()
    return temp_table_name

def reconcile_partner_payments(self, dataframe: DataFrame) -> NoReturn: #second function
    self.logger.info("Start reconcile_partner_payments")
    self.logger.info(f"df_col:{dataframe.columns}")
    partner_payment_ids = dataframe.select("partner_payment_id", 
    "effective_payroll_date").distinct()
    self.logger.info(f"head:{partner_payment_ids.head(3)}")
    self.logger.info(f"count:{partner_payment_ids.count()}")
    self.logger.info(f"c:{partner_payment_ids.columns}")
    temp_table_name = self._create_and_load_table(partner_payment_ids)
    table_schema = "partner_staging"
    update_query = """UPDATE abc.partner_payment as pp
                      JOIN partner_staging.{temp_table_name} as t on pp.id = 
           t.partner_payment_id
                      SET pp.reconciled = 1, pp.modify_ts = NOW() , pp.modify_user = 'ok 
                    successfull'""&quot"
  

    self.db.execute_insert_update(query_sql=update_query)
    self.db.drop_table(table_schema, temp_table_name)
    self.logger.info("End reconcile_partner_payments")


    def execute_insert_update(self, query_sql, args=()) -> None: #method being used in second_function
    
    try:
        cursor = self.get_cursor()
        self.start_transaction()
        cursor.execute(query_sql, args)
        self._connection.handle_unread_result()
        self.commit()
    except Error as e:
        stack = traceback.format_exc()
        self.rollback()
        print(stack)
        logger_func = Cache()[keys.LOGGER].info if keys.LOGGER in Cache() else print
        logger_func(f"stack_: {stack}")
        raise e
    finally:
        self.close_cursor()

 >  def _generate_table_name(self):#generate unique name
    self.logger.info("Start _generate_table_name")
    rand_str = random_str(length=4)
    self.logger.info("End _generate_table_name")
    return f"temp_{self.partner_name}_{self.company_name}_{self.payroll_name}_{rand_str}"

i tried defining the schema for the temp table however it is the same error.

英文:

I am working on one personal project.
There is multiple similar questions on this forum however everyone is case specific.
In my case i am creating and loading temp table, i am joining that table with existing table in DB and updating the same table based on temp table results. while executing db.execute_insert_update() it throws an exception : mysql.connector.errors.DatabaseError: 1412 (HY000): Table definition has changed, please retry transaction

 >  def _create_and_load_table(self, dataframe: DataFrame) -> str: #first_function
    self._log_entry()
    temp_table_name = self._generate_table_name()
    table_schema = "partner_staging"
    table_with_schema = f"{table_schema}.{temp_table_name}"

    self.df_mgr.jdbc_write(dataframe=dataframe, dbtable=table_with_schema, 
   check_count_before_write=True)
    self._log_exit()
    return temp_table_name

def reconcile_partner_payments(self, dataframe: DataFrame) -> NoReturn: #second function
    self.logger.info("Start reconcile_partner_payments")
    self.logger.info(f"df_col:{dataframe.columns}")
    partner_payment_ids = dataframe.select("partner_payment_id", 
    "effective_payroll_date").distinct()
    self.logger.info(f"head:{partner_payment_ids.head(3)}")
    self.logger.info(f"count:{partner_payment_ids.count()}")
    self.logger.info(f"c:{partner_payment_ids.columns}")
    temp_table_name = self._create_and_load_table(partner_payment_ids)
    table_schema = "partner_staging"
    update_query = """UPDATE abc.partner_payment as pp
                      JOIN partner_staging.{temp_table_name} as t on pp.id = 
           t.partner_payment_id
                      SET pp.reconciled = 1, pp.modify_ts = NOW() , pp.modify_user = 'ok 
                    successfull'"""
  

    self.db.execute_insert_update(query_sql=update_query)
    self.db.drop_table(table_schema, temp_table_name)
    self.logger.info("End reconcile_partner_payments")


    def execute_insert_update(self, query_sql, args=()) -> None: #method being used in second_function
    
    try:
        cursor = self.get_cursor()
        self.start_transaction()
        cursor.execute(query_sql, args)
        self._connection.handle_unread_result()
        self.commit()
    except Error as e:
        stack = traceback.format_exc()
        self.rollback()
        print(stack)
        logger_func = Cache()[keys.LOGGER].info if keys.LOGGER in Cache() else print
        logger_func(f"stack_: {stack}")
        raise e
    finally:
        self.close_cursor()

 >  def _generate_table_name(self):#generate unique name
    self.logger.info("Start _generate_table_name")
    rand_str = random_str(length=4)
    self.logger.info("End _generate_table_name")
    return f"temp_{self.partner_name}_{self.company_name}_{self.payroll_name}_{rand_str}"

i tried defining the schema for the temp table however it is the same error.

答案1

得分: 0

以下是已翻译的内容:

看起来你正在同时运行多个实例这个程序,我猜第二个实例开始时创建了一个你认为是临时的表,但实际上是与第一个实例完全相同名称的永久表。第二个程序在第一个程序正在使用表时执行了CREATE TABLE,导致混淆,DBMS说“我放弃!我不知道你想要什么!”

如何解决这个问题?

  1. 每次运行程序时生成一个随机或其他唯一的临时表名称,或者...

  2. 确保你的ORM在创建临时表时使用CREATE TEMPORARY TABLE tablename。临时表名称的作用范围既包括连接,也包括模式,因此你可以从不同实例使用相同的名称。

英文:

It looks to my like you're running more than one instance of this program you showed us at once. And, I guess the second instance starts out by creating a table that you think is temporary, but is actually a permanent table with the same exact name as the first instance's. The second program does a CREATE TABLE while the first one is using the table, and confusion ensues, and the DBMS says "I give up! I don't know what you want!"

How to fix this?

  1. Generate a random or otherwise unique name for the temporary table each time you run the program, or ...

  2. Make sure your ORM uses CREATE TEMPORARY TABLE tablename when it creates that temporary table. Temporary table names are scoped to the connection as well as to the schema, so you can use the same name from different instances.

huangapple
  • 本文由 发表于 2023年5月23日 01:06:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76308481.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定