Example #1
0
 async def _execute_trans(self, sql: TCL) -> result.Result:
     try:
         if sql.is_start:
             if self._trans:
                 raise Exception("Transactions cannot be nested.")
             self._trans = self._create_trans(sql.trans_args)
             await self._trans.begin(sql)
             return result.OK(0, 0, 0, 0, '', False)
         elif sql.is_commit:
             if self._trans:
                 await self._trans.commit(sql)
                 await self._trans.close()
                 self._trans = None
             return result.OK(0, 0, 0, 0, '', False)
         elif sql.is_rollback:
             if self._trans:
                 await self._trans.rollback(sql)
                 await self._trans.close()
                 self._trans = None
             return result.OK(0, 0, 0, 0, '', False)
         else:
             return result.Error(1000, "unknown what to do.")
     except Exception as e:
         await self._trans.close()
         self._trans = None
         return result.Error(1000, str(e))
Example #2
0
 async def rollback(self, sql: TCL) -> Optional[result.Result]:
     r = await self.a2pc_client.rollback(self.xid)
     if r.status == 0:
         self.status = TransStatus.END
         return result.OK(0, 0, 0, 0, "", False)
     else:
         return result.Error(r.status, r.msg)
Example #3
0
 async def _execute_ending(self, r: List[Union[result.Result,
                                               A2PCResponse]],
                           node: List[DBTableStrategyBackend], sql: DMLW):
     lock = r[-1]
     r = r[:-1]
     ending_sql = "COMMIT"
     return_v = None
     if not isinstance(lock, A2PCResponse):
         ending_sql = "ROLLBACK"
         return_v = result.Error(
             1000,
             "{} acquire lock fail: {}".format(str(sql.raw), str(lock)))
     elif lock.status != 0:
         logger.warning("{} acquire lock fail: {}".format(
             str(sql.raw), lock.msg))
         ending_sql = "ROLLBACK"
         return_v = result.Error(
             1000,
             "{} acquire lock fail: {}".format(str(sql.raw), lock.msg))
     if any([isinstance(i, result.Error) for i in r]):
         errors = [i for i in r if isinstance(i, result.Error)]
         for i in errors:
             logger.warning("{} error with code[{}],msg: {}".format(
                 str(sql.raw), i.error_code, i.message))
         ending_sql = "ROLLBACK"
         return_v = errors[0]
     c = []
     for i in node:
         c.append(self._execute_ending_sql(ending_sql, i))
     # 如果在 rollback 的时候异常,抛错给 app,即使数据库没有 rollback,
     # 也会在超时机制下回滚。 backend 遇到异常会关闭 session 触发 mysql
     # 的超时
     # 如果在 commit 的时候出现异常,返回错误给客户端,客户端可以重试,
     # 成功就走正常流程,或者选择回滚,回滚就走事务回滚流程
     await asyncio.gather(*c)
     if ending_sql == "ROLLBACK":
         return return_v  # type: ignore
     return result.OK(1, 0, 2, 0, "", False)
Example #4
0
    def read_result(self, _result: Optional[MySQLResult] = None) -> \
            result.Result:
        if _result is None:
            _result = self._result
        if _result.description is None:
            r = result.OK(
                _result.affected_rows,  # type: ignore
                _result.insert_id,  # type: ignore
                _result.server_status,  # type: ignore
                _result.warning_count,  # type: ignore
                _result.message,  # type: ignore
                _result.has_next)  # type: ignore
            return r

        descriptions = []
        for i in _result.fields:
            desc = result.ResultDescription(i.catalog, i.db, i.table_name,
                                            i.org_table, i.name, i.org_name,
                                            i.charsetnr, i.length, i.type_code,
                                            i.flags, i.scale)
            descriptions.append(desc)
        return result.ResultSet(_result.field_count, descriptions,
                                list(_result.rows))  # type: ignore