def do_special_upgrade(conn, cur, tenant_id_list, user, passwd):
    # special upgrade action
    #升级语句对应的action要写在下面的actions begin和actions end这两行之间,
    #因为基准版本更新的时候会调用reset_upgrade_scripts.py来清空actions begin和actions end
    #这两行之间的这些代码,如果不写在这两行之间的话会导致清空不掉相应的代码。
    # 主库升级流程没加滚动升级步骤,或混部阶段DDL测试有相关case覆盖前,混部开始禁DDL
    actions.set_parameter(cur, 'enable_ddl', 'False')
    ####========******####======== actions begin ========####******========####
    return
def do_normal_ddl_actions(cur):
    import normal_ddl_actions_post
    cls_list = reflect_action_cls_list(normal_ddl_actions_post,
                                       'NormalDDLActionPost')

    # set parameter
    if len(cls_list) > 0:
        actions.set_parameter(cur, 'enable_sys_table_ddl', 'True')
        ori_enable_ddl = actions.get_ori_enable_ddl(cur)
        if ori_enable_ddl == 0:
            actions.set_parameter(cur, 'enable_ddl', 'True')

    for cls in cls_list:
        logging.info('do normal ddl acion, seq_num: %d', cls.get_seq_num())
        action = cls(cur)
        action.dump_before_do_action()
        if False == action.skip_action():
            action.check_before_do_action()
            action.do_action()
        else:
            logging.info("skip ddl action, seq_num: %d", cls.get_seq_num())
        action.dump_after_do_action()
        action.check_after_do_action()

    # reset parameter
    if len(cls_list) > 0:
        if ori_enable_ddl == 0:
            actions.set_parameter(cur, 'enable_ddl', 'False')
        actions.set_parameter(cur, 'enable_sys_table_ddl', 'False')
def do_each_tenant_ddl_actions(cur, tenant_id_list):
    import each_tenant_ddl_actions_post
    # 组户级系统表没法通过虚拟表暴露,需要根据版本决定查哪张实体表
    query_cur = QueryCursor(cur)
    version = fetch_observer_version(query_cur)
    all_table_name = "__all_table"
    if (cmp(version, "2.2.60") >= 0):
        all_table_name = "__all_table_v2"

    cls_list = reflect_action_cls_list(each_tenant_ddl_actions_post,
                                       'EachTenantDDLActionPost')

    # set parameter
    if len(cls_list) > 0:
        actions.set_parameter(cur, 'enable_sys_table_ddl', 'True')
        ori_enable_ddl = actions.get_ori_enable_ddl(cur)
        if ori_enable_ddl == 0:
            actions.set_parameter(cur, 'enable_ddl', 'True')

    for cls in cls_list:
        logging.info('do each tenant ddl acion, seq_num: %d',
                     cls.get_seq_num())
        action = cls(cur, tenant_id_list)
        action.set_all_table_name(all_table_name)
        action.dump_before_do_action()
        if False == action.skip_pre_check():
            action.check_before_do_action()
        else:
            logging.info("skip pre check. seq_num: %d", cls.get_seq_num())
        # 系统租户组户级系统表创建成功会覆盖普通租户系统表,所以系统租户要最后建表
        for tenant_id in action.get_tenant_id_list():
            action.dump_before_do_each_tenant_action(tenant_id)
            if False == action.skip_each_tenant_action(tenant_id):
                action.check_before_do_each_tenant_action(tenant_id)
                action.do_each_tenant_action(tenant_id)
            else:
                logging.info(
                    "skip each tenant ddl action, seq_num: %d, tenant_id: %d",
                    cls.get_seq_num(), tenant_id)
            action.dump_after_do_each_tenant_action(tenant_id)
            action.check_after_do_each_tenant_action(tenant_id)
        action.dump_after_do_action()
        action.check_after_do_action()

    # reset parameter
    if len(cls_list) > 0:
        if ori_enable_ddl == 0:
            actions.set_parameter(cur, 'enable_ddl', 'False')
        actions.set_parameter(cur, 'enable_sys_table_ddl', 'False')
def run_upgrade_job(conn, cur, version):
  try:
    logging.info("start to run upgrade job, version:{0}".format(version))
    # pre check
    if (check_can_run_upgrade_job(cur, version) == True):
      conn.autocommit = True
      # disable enable_ddl
      ori_enable_ddl = actions.get_ori_enable_ddl(cur)
      if ori_enable_ddl == 1:
        actions.set_parameter(cur, 'enable_ddl', 'False')
      # get max_used_job_id
      max_used_job_id = get_max_used_job_id(cur)
      # run upgrade job
      sql = """alter system run upgrade job '{0}'""".format(version)
      logging.info(sql)
      cur.execute(sql)
      # check upgrade job result
      check_upgrade_job_result(cur, version, max_used_job_id)
      # reset enable_ddl
      if ori_enable_ddl == 1:
        actions.set_parameter(cur, 'enable_ddl', 'True')
  except Exception, e:
    logging.warn("run upgrade job failed, version:{0}".format(version))
    raise e
Example #5
0
def do_normal_ddl_actions(cur):
    import normal_ddl_actions_pre
    upgrade_params = UpgradeParams()
    cls_list = reflect_action_cls_list(normal_ddl_actions_pre,
                                       'NormalDDLActionPre')

    # check if pre upgrade script can run reentrantly
    query_cur = QueryCursor(cur)
    version = fetch_observer_version(query_cur)
    can_skip = False
    if (cmp(version, "2.2.77") >= 0 and cmp(version, "3.0.0") < 0):
        can_skip = True
    elif (cmp(version, "3.1.1") >= 0):
        can_skip = True
    else:
        can_skip = False

    # set parameter
    if len(cls_list) > 0:
        actions.set_parameter(cur, 'enable_sys_table_ddl', 'True')
        ori_enable_ddl = actions.get_ori_enable_ddl(cur)
        if ori_enable_ddl == 0:
            actions.set_parameter(cur, 'enable_ddl', 'True')

    for cls in cls_list:
        logging.info('do normal ddl acion, seq_num: %d', cls.get_seq_num())
        action = cls(cur)
        action.dump_before_do_action()
        if False == can_skip or False == action.skip_action():
            action.check_before_do_action()
            action.do_action()
        else:
            logging.info("skip ddl action, seq_num: %d", cls.get_seq_num())
        action.dump_after_do_action()
        action.check_after_do_action()

    # reset parameter
    if len(cls_list) > 0:
        if ori_enable_ddl == 0:
            actions.set_parameter(cur, 'enable_ddl', 'False')
        actions.set_parameter(cur, 'enable_sys_table_ddl', 'False')
def modify_foreign_key_column_position_info(conn, cur):
    try:
        conn.autocommit = True
        # disable ddl
        ori_enable_ddl = actions.get_ori_enable_ddl(cur)
        if ori_enable_ddl == 1:
            actions.set_parameter(cur, 'enable_ddl', 'False')
        tenant_ids = get_tenant_ids(cur)
        log('tenant_ids: {0}'.format(tenant_ids))
        for tenant_id in tenant_ids:
            sql = """alter system change tenant tenant_id = {0}""".format(
                tenant_id)
            log(sql)
            cur.execute(sql)
            tenant_id_in_sql = 0
            if 1 == tenant_id:
                tenant_id_in_sql = 1
            # 查出租户下所有未被删除的外键
            sql = """select /*+ QUERY_TIMEOUT(1500000000) */ foreign_key_id from oceanbase.__all_foreign_key where tenant_id = {0}""".format(
                tenant_id_in_sql)
            log(sql)
            foreign_key_id_rows = query(cur, sql)
            fk_num = len(foreign_key_id_rows)
            cnt = 0
            # 遍历每个外键,检查 oceanbase.__all_foreign_key_column 中记录的 position 信息是否为 0,如果为 0,需要更新为正确的值
            while cnt < fk_num:
                foreign_key_id = foreign_key_id_rows[cnt][0]
                sql = """select /*+ QUERY_TIMEOUT(1500000000) */ child_column_id, parent_column_id from oceanbase.__all_foreign_key_column where foreign_key_id = {0} and position = 0 and tenant_id = {1} order by gmt_create asc""".format(
                    foreign_key_id, tenant_id_in_sql)
                log(sql)
                need_update_rows = query(cur, sql)
                fk_col_num = len(need_update_rows)
                if fk_col_num > 0:
                    position = 1
                    # 遍历特定外键里的每个 position 信息为 0 的列
                    while position <= fk_col_num:
                        child_column_id = need_update_rows[position - 1][0]
                        parent_column_id = need_update_rows[position - 1][1]
                        # 在 oceanbase.__all_foreign_key_column_history 里面更新 position 的值
                        sql = """update /*+ QUERY_TIMEOUT(150000000) */ oceanbase.__all_foreign_key_column_history set position = {0} where foreign_key_id = {1} and child_column_id = {2} and parent_column_id = {3} and tenant_id = {4}""".format(
                            position, foreign_key_id, child_column_id,
                            parent_column_id, tenant_id_in_sql)
                        log(sql)
                        cur.execute(sql)
                        if cur.rowcount == 0:
                            logging.warn(
                                "affected rows is 0 when update oceanbase.__all_foreign_key_column_history"
                            )
                            raise e
                        # 在 oceanbase.__all_foreign_key_column 里面更新 position 的值
                        sql = """update /*+ QUERY_TIMEOUT(150000000) */ oceanbase.__all_foreign_key_column set position = {0} where foreign_key_id = {1} and child_column_id = {2} and parent_column_id = {3} and tenant_id = {4}""".format(
                            position, foreign_key_id, child_column_id,
                            parent_column_id, tenant_id_in_sql)
                        log(sql)
                        cur.execute(sql)
                        if cur.rowcount != 1:
                            logging.warn(
                                "affected rows is not 1 when update oceanbase.__all_foreign_key_column"
                            )
                            raise e
                        position = position + 1
                cnt = cnt + 1
        # 还原默认 tenant
        sys_tenant_id = 1
        sql = """alter system change tenant tenant_id = {0}""".format(
            sys_tenant_id)
        log(sql)
        cur.execute(sql)

        # enable ddl
        if ori_enable_ddl == 1:
            actions.set_parameter(cur, 'enable_ddl', 'True')
    except Exception, e:
        logging.warn("modify foreign key column position failed")
        raise e
def fill_priv_file_column_for_all_user(conn, cur):
    try:
        conn.autocommit = True
        # disable ddl
        ori_enable_ddl = actions.get_ori_enable_ddl(cur)
        if ori_enable_ddl == 1:
            actions.set_parameter(cur, 'enable_ddl', 'False')
        tenant_ids = get_tenant_ids(cur)
        log('tenant_ids: {0}'.format(tenant_ids))
        for tenant_id in tenant_ids:
            sql = """alter system change tenant tenant_id = {0}""".format(
                tenant_id)
            log(sql)
            cur.execute(sql)
            tenant_id_in_sql = 0
            if 1 == tenant_id:
                tenant_id_in_sql = 1

            begin_user_id = 0
            begin_schema_version = 0
            fetch_num = 1000

            while (True):
                query_limit = """
                  where tenant_id = {0} and (user_id, schema_version) > ({1}, {2})
                  order by tenant_id, user_id, schema_version
                  limit {3}""".format(tenant_id_in_sql, begin_user_id,
                                      begin_schema_version, fetch_num)

                sql = """select /*+ QUERY_TIMEOUT(1500000000) */ user_id, schema_version
                 from oceanbase.__all_user_history""" + query_limit
                log(sql)
                result_rows = query(cur, sql)
                log("select rows = " + str(cur.rowcount))

                if len(result_rows) <= 0:
                    break
                else:
                    last_schema_version = result_rows[-1][1]
                    last_user_id = result_rows[-1][0]
                    condition = """
                  where priv_alter = 1 and priv_create = 1 and priv_create_user = 1 and priv_delete = 1
                         and priv_drop = 1 and priv_insert = 1 and priv_update = 1 and priv_select = 1
                         and priv_index = 1 and priv_create_view = 1 and priv_show_view = 1 and priv_show_db = 1
                         and priv_super = 1 and priv_create_synonym = 1
                         and tenant_id = {0} and (user_id, schema_version) > ({1}, {2})
                         and (user_id, schema_version) <= ({3}, {4})
                  """.format(tenant_id_in_sql, begin_user_id,
                             begin_schema_version, last_user_id,
                             last_schema_version)

                    sql = """update /*+ QUERY_TIMEOUT(150000000) */ oceanbase.__all_user_history
                   set priv_file = 1""" + condition
                    log(sql)
                    cur.execute(sql)
                    log("update rows = " + str(cur.rowcount))

                    condition = """
                  where priv_super = 1 and tenant_id = {0} and (user_id, schema_version) > ({1}, {2})
                         and (user_id, schema_version) <= ({3}, {4})
                  """.format(tenant_id_in_sql, begin_user_id,
                             begin_schema_version, last_user_id,
                             last_schema_version)

                    sql = """update /*+ QUERY_TIMEOUT(150000000) */ oceanbase.__all_user_history
                   set priv_alter_tenant = 1,
                       priv_alter_system = 1,
                       priv_create_resource_unit = 1,
                       priv_create_resource_pool = 1 """ + condition
                    log(sql)
                    cur.execute(sql)

                    begin_schema_version = last_schema_version
                    begin_user_id = last_user_id

            begin_user_id = 0
            while (True):
                query_limit = """
                   where tenant_id = {0} and user_id > {1}
                   order by tenant_id, user_id
                   limit {2}""".format(tenant_id_in_sql, begin_user_id,
                                       fetch_num)
                sql = """select /*+ QUERY_TIMEOUT(1500000000) */ user_id
                 from oceanbase.__all_user""" + query_limit
                log(sql)
                result_rows = query(cur, sql)
                log("select rows = " + str(cur.rowcount))

                if len(result_rows) <= 0:
                    break
                else:
                    end_user_id = result_rows[-1][0]
                    condition = """
                   where priv_alter = 1 and priv_create = 1 and priv_create_user = 1 and priv_delete = 1
                         and priv_drop = 1 and priv_insert = 1 and priv_update = 1 and priv_select = 1
                         and priv_index = 1 and priv_create_view = 1 and priv_show_view = 1 and priv_show_db = 1
                         and priv_super = 1 and priv_create_synonym = 1
                         and tenant_id = {0} and user_id > {1} and user_id <= {2}
                  """.format(tenant_id_in_sql, begin_user_id, end_user_id)
                    sql = """update /*+ QUERY_TIMEOUT(150000000) */ oceanbase.__all_user
                   set priv_file = 1 """ + condition
                    log(sql)
                    cur.execute(sql)
                    log("update rows = " + str(cur.rowcount))

                    condition = """
                   where priv_super = 1
                         and tenant_id = {0} and user_id > {1} and user_id <= {2}
                  """.format(tenant_id_in_sql, begin_user_id, end_user_id)
                    sql = """update /*+ QUERY_TIMEOUT(150000000) */ oceanbase.__all_user
                   set priv_alter_tenant = 1,
                       priv_alter_system = 1,
                       priv_create_resource_unit = 1,
                       priv_create_resource_pool = 1 """ + condition
                    log(sql)
                    cur.execute(sql)

                    begin_user_id = end_user_id

        # 还原默认 tenant
        sys_tenant_id = 1
        sql = """alter system change tenant tenant_id = {0}""".format(
            sys_tenant_id)
        log(sql)
        cur.execute(sql)

        # enable ddl
        if ori_enable_ddl == 1:
            actions.set_parameter(cur, 'enable_ddl', 'True')
    except Exception, e:
        logging.warn("exec fill priv_file to all_user failed")
        raise e
def modify_trigger(conn, cur, tenant_ids):
    try:
        conn.autocommit = True
        # disable ddl
        ori_enable_ddl = actions.get_ori_enable_ddl(cur)
        if ori_enable_ddl == 1:
            actions.set_parameter(cur, 'enable_ddl', 'False')
        log('tenant_ids: {0}'.format(tenant_ids))
        for tenant_id in tenant_ids:
            sql = """alter system change tenant tenant_id = {0}""".format(
                tenant_id)
            log(sql)
            cur.execute(sql)
            #####implement#####
            trigger_sql = """
update __all_tenant_trigger
set
package_spec_source = replace(
package_spec_source,
'FUNCTION UPDATING(column VARCHAR2 := NULL) RETURN BOOL\;',
'FUNCTION UPDATING(column_name VARCHAR2 := NULL) RETURN BOOL\;'
),
package_body_source = replace(replace(
package_body_source,
'
PROCEDURE init_trigger(update_columns IN STRINGARRAY) IS
BEGIN
  NULL\;
END\;
',
'
PROCEDURE init_trigger(update_columns IN STRINGARRAY) IS
BEGIN
  update_columns_ := STRINGARRAY()\;
  update_columns_.EXTEND(update_columns.COUNT)\;
  FOR i IN 1 .. update_columns.COUNT LOOP
    update_columns_(i) := update_columns(i)\;
  END LOOP\;
END\;
'),
'
FUNCTION UPDATING(column VARCHAR2 := NULL) RETURN BOOL IS
BEGIN
  RETURN (dml_event_ = 4)\;
END\;
',
'
FUNCTION UPDATING(column_name VARCHAR2 := NULL) RETURN BOOL IS
  is_updating BOOL\;
BEGIN
  is_updating := (dml_event_ = 4)\;
  IF (is_updating AND column_name IS NOT NULL) THEN
    is_updating := FALSE\;
    FOR i IN 1 .. update_columns_.COUNT LOOP
      IF (UPPER(update_columns_(i)) = UPPER(column_name)) THEN is_updating := TRUE\; EXIT\; END IF\;
    END LOOP\;
  END IF\;
  RETURN is_updating\;
END\;
'); """

            log(trigger_sql)
            cur.execute(trigger_sql)
            log("update rows = " + str(cur.rowcount))

            trigger_history_sql = """
update __all_tenant_trigger_history
set
package_spec_source = replace(
package_spec_source,
'FUNCTION UPDATING(column VARCHAR2 := NULL) RETURN BOOL\;',
'FUNCTION UPDATING(column_name VARCHAR2 := NULL) RETURN BOOL\;'
),
package_body_source = replace(replace(
package_body_source,
'
PROCEDURE init_trigger(update_columns IN STRINGARRAY) IS
BEGIN
  NULL\;
END\;
',
'
PROCEDURE init_trigger(update_columns IN STRINGARRAY) IS
BEGIN
  update_columns_ := STRINGARRAY()\;
  update_columns_.EXTEND(update_columns.COUNT)\;
  FOR i IN 1 .. update_columns.COUNT LOOP
    update_columns_(i) := update_columns(i)\;
  END LOOP\;
END\;
'),
'
FUNCTION UPDATING(column VARCHAR2 := NULL) RETURN BOOL IS
BEGIN
  RETURN (dml_event_ = 4)\;
END\;
',
'
FUNCTION UPDATING(column_name VARCHAR2 := NULL) RETURN BOOL IS
  is_updating BOOL\;
BEGIN
  is_updating := (dml_event_ = 4)\;
  IF (is_updating AND column_name IS NOT NULL) THEN
    is_updating := FALSE\;
    FOR i IN 1 .. update_columns_.COUNT LOOP
      IF (UPPER(update_columns_(i)) = UPPER(column_name)) THEN is_updating := TRUE\; EXIT\; END IF\;
    END LOOP\;
  END IF\;
  RETURN is_updating\;
END\;
')
where is_deleted = 0; """

            log(trigger_history_sql)
            cur.execute(trigger_history_sql)
            log("update rows = " + str(cur.rowcount))

            #####implement end#####

        # 还原默认 tenant
        sys_tenant_id = 1
        sql = """alter system change tenant tenant_id = {0}""".format(
            sys_tenant_id)
        log(sql)
        cur.execute(sql)

        # enable ddl
        if ori_enable_ddl == 1:
            actions.set_parameter(cur, 'enable_ddl', 'True')
    except Exception, e:
        logging.warn("exec modify trigger failed")
        raise e
def disable_major_freeze(conn, cur):
  try:
    actions.set_parameter(cur, "enable_major_freeze", 'False')
  except Exception, e:
    logging.warn("disable enable_major_freeze failed")
    raise e
def statistic_primary_zone_count(conn, cur):
  try:
    ###### disable ddl
    ori_enable_ddl = actions.get_ori_enable_ddl(cur)
    if ori_enable_ddl == 1:
      actions.set_parameter(cur, 'enable_ddl', 'False')

    # check record in rs_job
    count_sql = """select count(*) from oceanbase.__all_rootservice_job
            where job_type = 'STATISTIC_PRIMARY_ZONE_ENTITY_COUNT';"""
    result = query(cur, count_sql)
    job_count = 0
    if (1 != len(result)) :
      logging.warn("unexpected sql output")
      raise e
    else :
      job_count = result[0][0]
      # run job
      sql = "alter system run job 'STATISTIC_PRIMARY_ZONE_ENTITY_COUNT';"
      logging.info(sql)
      cur.execute(sql)
      # wait job finish
      times = 180
      ## 先检查job count变化
      count_check = False
      while times > 0:
        result = query(cur, count_sql)
        if (1 != len(result)):
          logging.warn("unexpected sql output")
          raise e
        elif (result[0][0] > job_count):
          count_check = True
          logging.info('statistic_primary_zone_entity_count job detected')
          break
        time.sleep(10)
        times -= 1
        if times == 0:
          raise MyError('statistic_primary_zone_entity_count job failed!')

      ## 继续检查job status状态
      status_sql = """select job_status from oceanbase.__all_rootservice_job
                      where job_type = 'STATISTIC_PRIMARY_ZONE_ENTITY_COUNT' order by job_id desc limit 1;"""
      status_check = False
      while times > 0 and count_check == True:
        result = query(cur, status_sql)
        if (0 == len(result)):
          logging.warn("unexpected sql output")
          raise e
        elif (1 != len(result) or 1 != len(result[0])):
          logging.warn("result len not match")
          raise e
        elif result[0][0] == "FAILED":
          logging.warn("run statistic_primary_zone_entity_count job faild")
          raise e
        elif result[0][0] == "INPROGRESS":
          logging.info('statistic_primary_zone_entity_count job is still running')
        elif result[0][0] == "SUCCESS":
          status_check = True
          break;
        else:
          logging.warn("invalid result: {0}" % (result[0][0]))
          raise e
        time.sleep(10)
        times -= 1
        if times == 0:
          raise MyError('check statistic_primary_zone_entity_count job failed!')

      if (status_check == True and count_check == True):
        logging.info('check statistic_primary_zone_entity_count job success')
      else:
        logging.warn("run statistic_primary_zone_entity_count job faild")
        raise e

    # enable ddl
    if ori_enable_ddl == 1:
      actions.set_parameter(cur, 'enable_ddl', 'True')
  except Exception, e:
    logging.warn("run statistic_primary_zone_entity_count job failed")
    raise e