admin 发表于 2024-1-12 22:42:49

godba




这是一个Python脚本,使用cx_Oracle模块连接Oracle数据库,并从一个数据库中的表获取连接信息,然后遍历这些连接信息并连接到对应的数据库,查询其中的用户信息,最后将查询结果插入到另一个数据库中的表中。该脚本的作用是将多个Oracle数据库的用户信息收集到一个统一的库中,方便管理和监控。

具体来说,该脚本会执行以下步骤:

使用cx_Oracle模块连接到一个Oracle数据库,从其中的godba_add_db表获取多个目标数据库的连接信息,包括IP地址、监听端口、服务名、用户名、密码和数据库UUID等。

遍历连接信息,对于每个目标数据库,使用cx_Oracle模块连接到该数据库,查询其中的dba_users表,获取其中的用户信息,包括用户名、用户ID、密码、账号状态、锁定时间、过期时间、默认表空间、临时表空间、本地临时表空间、创建时间、配置文件、初始资源消费者组、外部名称、密码版本、启用版本、身份验证类型、仅代理连接、常用设置、上次登录、Oracle维护、继承、默认排序规则、隐式用户、全局分片、密码更改时间和检查时间等。

将查询结果插入到另一个Oracle数据库的godba_users表中,也包括上述所有字段,以及db_uuid字段,用于标识该用户信息所属的数据库。

关闭游标和连接,并提交事务。

import cx_Oracle

#从rep库获取数据库连接信息
target_conn = cx_Oracle.connect("zhyu/zhyu@192.168.56.101:1521/ora19")
target_cursor = target_conn.cursor()
dbl_query = "SELECT IP_ADDRESS, LISTENER_PORT, SERVICE_NAME, USERNAME, PASSWORD, DB_UUID FROM godba_add_db"
target_cursor.execute(dbl_query)
#遍历连接信息,从源库查询信息并存放到rep库
for IP_ADDRESS, LISTENER_PORT, SERVICE_NAME, USERNAME, PASSWORD, DB_UUID in target_cursor.fetchall():
source_conn = cx_Oracle.connect(f"{USERNAME}/{PASSWORD}@{IP_ADDRESS}:{LISTENER_PORT}/{SERVICE_NAME}")
source_cursor = source_conn.cursor()
source_cursor.execute("SELECT username,user_id,password,account_status,lock_date,expiry_date,default_tablespace,temporary_tablespace,local_temp_tablespace,created,profile,INITIAL_RSRC_CONSUMER_GROUP,EXTERNAL_NAME,PASSWORD_VERSIONS,EDITIONS_ENABLED,AUTHENTICATION_TYPE,PROXY_ONLY_CONNECT,COMMON,LAST_LOGIN,ORACLE_MAINTAINED,INHERITED,DEFAULT_COLLATION,IMPLICIT,ALL_SHARD,PASSWORD_CHANGE_DATE,to_char(sysdate,'yyyymmddhh24miss') check_time FROM dba_users")
for result in source_cursor.fetchall():
    target_cursor.execute("INSERT INTO godba_users (username,user_id,password,account_status,lock_date,expiry_date,default_tablespace,temporary_tablespace,local_temp_tablespace,created,profile,INITIAL_RSRC_CONSUMER_GROUP,EXTERNAL_NAME,PASSWORD_VERSIONS,EDITIONS_ENABLED,AUTHENTICATION_TYPE,PROXY_ONLY_CONNECT,COMMON,LAST_LOGIN,ORACLE_MAINTAINED,INHERITED,DEFAULT_COLLATION,IMPLICIT,ALL_SHARD,PASSWORD_CHANGE_DATE,check_time,db_uuid) VALUES (:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15, :16, :17, :18, :19, :20, :21, :22, :23, :24, :25, :26, :27)", result + (DB_UUID,))
#关闭游标,关闭连接
source_cursor.close()
source_conn.close()
target_conn.commit()
target_cursor.close()
target_conn.close()

admin 发表于 2024-1-12 22:45:45

import cx_Oracle
import logging
import time

# 配置日志记录器
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.FileHandler("database.log")
handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

# 从rep库获取数据库连接信息
target_conn = cx_Oracle.connect("zhyu/zhyu@192.168.56.101:1521/ora19")
target_cursor = target_conn.cursor()
dbl_query = "SELECT IP_ADDRESS, LISTENER_PORT, SERVICE_NAME, USERNAME, PASSWORD, DB_UUID FROM godba_add_db"
target_cursor.execute(dbl_query)

# 遍历连接信息,从源库查询信息并存放到rep库
for IP_ADDRESS, LISTENER_PORT, SERVICE_NAME, USERNAME, PASSWORD, DB_UUID in target_cursor.fetchall():
    retry_count = 0
    while retry_count < 3:
      try:
            logger.info(f"Connecting to {IP_ADDRESS}:{LISTENER_PORT}/{SERVICE_NAME}...")
            source_conn = cx_Oracle.connect(
                f"{USERNAME}/{PASSWORD}@{IP_ADDRESS}:{LISTENER_PORT}/{SERVICE_NAME}")
            source_cursor = source_conn.cursor()
            source_cursor.execute(
                "SELECT username,user_id,password,account_status,lock_date,expiry_date,default_tablespace,temporary_tablespace,local_temp_tablespace,created,profile,INITIAL_RSRC_CONSUMER_GROUP,EXTERNAL_NAME,PASSWORD_VERSIONS,EDITIONS_ENABLED,AUTHENTICATION_TYPE,PROXY_ONLY_CONNECT,COMMON,LAST_LOGIN,ORACLE_MAINTAINED,INHERITED,DEFAULT_COLLATION,IMPLICIT,ALL_SHARD,PASSWORD_CHANGE_DATE,to_char(sysdate,'yyyymmddhh24miss') check_time FROM dba_users")
            for result in source_cursor.fetchall():
                target_cursor.execute("INSERT INTO godba_users (username,user_id,password,account_status,lock_date,expiry_date,default_tablespace,temporary_tablespace,local_temp_tablespace,created,profile,INITIAL_RSRC_CONSUMER_GROUP,EXTERNAL_NAME,PASSWORD_VERSIONS,EDITIONS_ENABLED,AUTHENTICATION_TYPE,PROXY_ONLY_CONNECT,COMMON,LAST_LOGIN,ORACLE_MAINTAINED,INHERITED,DEFAULT_COLLATION,IMPLICIT,ALL_SHARD,PASSWORD_CHANGE_DATE,check_time,db_uuid) VALUES (:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15, :16, :17, :18, :19, :20, :21, :22, :23, :24, :25, :26, :27)",
                                    result + (DB_UUID,))
            logger.info(f"Successfully processed {IP_ADDRESS}:{LISTENER_PORT}/{SERVICE_NAME}.")
            break
      except cx_Oracle.DatabaseError as e:
            logger.error(f"Unable to connect to {IP_ADDRESS}:{LISTENER_PORT}/{SERVICE_NAME}. Retry count: {retry_count+1}", exc_info=True)
            if retry_count == 2:
                logger.error(f"Connection failed after 3 retries. Skipping to the next database.")
            else:
                retry_count += 1
                time.sleep(5)# Wait for 5 seconds before retrying

    # 关闭游标,关闭连接
    source_cursor.close()
    source_conn.close()

target_conn.commit()
target_cursor.close()
target_conn.close()


在上述代码中,我们使用了try-except块来捕获cx_Oracle.DatabaseError异常,该异常表示数据库连接失败。如果连接失败,将打印错误消息,并在重试次数小于3时进行重试。如果连续尝试3次都无法连接成功,则跳过当前数据库,继续下一个数据库的处理。
请注意,我在连接失败后添加了一个5秒的延迟,以避免频繁尝试连接导致过多的资源消耗。你可以根据实际情况调整这个延迟时间。
另外,我还将提交事务的操作移动到了循环外部,在处理完所有数据库后进行提交,以提高效率。
页: [1]
查看完整版本: godba