使用Datax批量将mysql数据导入hive

试想一个场景,将mysql中的jrxd 数据库中的所有表导入到hive中的finance数据库中

一、准备工作

在hive中创建一个数据库: create database finance;

在mysql数据库,查询jrxd下的所有表名,复制到/root/tables.txt文件中

select table_name from information_schema.`TABLES` where table_schema = 'jrxd'

将其查询的内容,复制到table.txt中

复制代码
channel_info            
com_manager_info        
dict_citys              
dict_product            
dict_provinces          
drawal_address          
drawal_apply            
drawal_companys         
loan_apply              
loan_apply_credit_report
loan_apply_salary       
loan_credit             
repay_plan              
repay_plan_item         
repay_plan_item_his     
user_det                
user_md5                
user_ocrlog             
user_quota             
users

二、批量生成hive的建表语句

python 代码编写

python 连接 mysql 需要 pymysql 的支持,所以需要先在 windows 上安装这个软件:

复制代码
pip install pymysql
python 复制代码
# 给定一个数据库的名字和表的名字,自动生成hive的建表语句
import sys

import pymysql


def getDBData(dbName, tableName):
	# 查询mysql的元数据,根据数据库的名字和表的名字查询改表对应的字段和类型
	# 连接数据库(指定charset避免中文乱码)
	conn = pymysql.connect(
		host='bigdata01',
		user='root',
		password='123456',
		database='information_schema',
		charset='utf8mb4',
		cursorclass=pymysql.cursors.DictCursor  # 返回字典格式,更易读
	)
	cursor = conn.cursor()
	sql = """
	            SELECT column_name, data_type 
	            FROM information_schema.`COLUMNS` 
	            WHERE TABLE_SCHEMA = %s AND table_name = %s
	            ORDER BY ordinal_position  # 按字段顺序排序
	        """
	# 执行sql语句
	cursor.execute(sql, (dbName, tableName))
	result=cursor.fetchall()
	# 关键修复:统一将字典的key转为小写,兼容大小写场景
	result_lower = []
	for item in result:
		lower_item = {k.lower(): v for k, v in item.items()}
		result_lower.append(lower_item)

	#print(result_lower)
	"""
	[{'column_name': 'id', 'data_type': 'bigint'}, {'column_name': 'name', 'data_type': 'varchar'},
	 {'column_name': 'channel_code', 'data_type': 'varchar'}, {'column_name': 'channel_type', 'data_type': 'varchar'},
	 {'column_name': 'channel_cus_fee', 'data_type': 'decimal'},
	 {'column_name': 'channel_perf_fee', 'data_type': 'decimal'},
	 {'column_name': 'updated_at', 'data_type': 'datetime'}, {'column_name': 'created_at', 'data_type': 'datetime'}]
	"""

	cursor.close()
	conn.close()

	return result_lower

# 完善MySQL到Hive的类型映射(覆盖更多场景,符合生产规范)
MYSQL_TO_HIVE_TYPE_MAPPING = {
    # 整数类型
    'tinyint': 'TINYINT',
    'smallint': 'SMALLINT',
    'int': 'INT',
    'integer': 'INT',
    'bigint': 'BIGINT',
    'bit': 'BOOLEAN',  # MySQL bit(1) 对应Hive布尔值
    # 浮点/定点类型
    'float': 'FLOAT',
    'double': 'DOUBLE',
    'decimal': 'DECIMAL',  # 保留DECIMAL类型(金融场景不建议转STRING)
    'numeric': 'DECIMAL',
    # 字符串类型
    'varchar': 'STRING',
    'char': 'STRING',
    'text': 'STRING',
    'tinytext': 'STRING',
    'mediumtext': 'STRING',
    'longtext': 'STRING',
    'enum': 'STRING',
    'set': 'STRING',
    # 日期时间类型
    'date': 'DATE',
    'datetime': 'STRING',  # 避时区问题,建议存字符串
    'timestamp': 'STRING',
    'time': 'STRING',
    'year': 'INT',
    # 二进制类型
    'binary': 'BINARY',
    'varbinary': 'BINARY',
    'blob': 'BINARY',
    'tinyblob': 'BINARY',
    'mediumblob': 'BINARY',
    'longblob': 'BINARY',
    # 其他类型
    'boolean': 'BOOLEAN',
    'bool': 'BOOLEAN'
}
def generateHiveCreateSql(dbName, tableName,field_info):
	hive_columns = []
	for tuple in field_info:
		column_name = tuple['column_name']
		data_type = tuple['data_type']
		# 根据mysql的字段类型获取hive对应的字段类型
		hive_type=MYSQL_TO_HIVE_TYPE_MAPPING.get(data_type, "string")
		hive_columns.append(f"{column_name} {hive_type}")
	print(",".join(hive_columns))
	sql = f"""
	    CREATE  TABLE IF NOT EXISTS ods_jrxd_{tableName} (
		{','.join(hive_columns)}
		)
		COMMENT '{dbName}.{tableName}'
		ROW FORMAT DELIMITED
			FIELDS TERMINATED BY ',';
	"""
	return sql


if __name__ == '__main__':
	# 校验外部参数
	if len(sys.argv) != 3:
		print("请传入数据库的名字和表的名字")

	dbName = sys.argv[1]
	tableName = sys.argv[2]
	print(dbName, tableName)
	field_info=getDBData(dbName, tableName)
	create_hive_table_sql=generateHiveCreateSql(dbName, tableName, field_info)
	print(create_hive_table_sql)
	with open("./hive_create_table.sql","a",encoding="utf-8") as f:
		f.write(create_hive_table_sql)

shell 代码:

复制代码
#!/bin/bash
while read x1
do
   python AutoCreateHiveSql.py jrxd $x1
done < /root/tables.txt

将 python 代码,上传到 /home/scripts

复制代码
运行脚本:
./datax_autosql_finance.sh

将 sql 语句粘贴到 hive 窗口运行即可

三、批量生成 datax 的 json 文件

编写一个python脚本,用于生成datax的json文件

复制代码
`COLUMNS` 是一个视图,不是一个表

需要用到python的以下技术点
1)python读取mysql数据?   spark_pro
2)知道mysql表的元数据在哪里?
select column_name ,data_type from information_schema.`COLUMNS` where TABLE_SCHEMA = 'spark_project' and table_name = 't_order'
3)一些函数的用法
4)文件的写入 IO流

编写python代码

第一步:能够通过python读取mysql的数据库的表

复制代码
import pymysql
def getDBData(dbName,tableName):
    db_connection = pymysql.connect(
        host="bigdata01",
        port=3306,
        user="root",
        password="123456",
        database='information_schema'
    )
    cursor = db_connection.cursor()
    sql = f"select column_name ,data_type from information_schema.`COLUMNS` where TABLE_SCHEMA = '{dbName}' and table_name = '{tableName}' order by ordinal_position"
    cursor.execute(sql)
    result = cursor.fetchall()
    cursor.close()
    db_connection.close()
    return result

if __name__ == '__main__':
    result = getDBData("spark_project","oms_order")
    print(result)

第二步:使用json.dump将文件保存起来

第三步:拼接json文件

复制代码
import json
import sys

import pymysql


def getDBData(dbName, tableName):
    # 查询mysql的元数据,根据数据库的名字和表的名字查询改表对应的字段和类型
    # 连接数据库(指定charset避免中文乱码)
    conn = pymysql.connect(
        host='bigdata01',
        user='root',
        password='123456',
        database='information_schema',
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor  # 返回字典格式,更易读
    )
    cursor = conn.cursor()
    sql = """
                SELECT column_name, data_type 
                FROM information_schema.`COLUMNS` 
                WHERE TABLE_SCHEMA = %s AND table_name = %s
                ORDER BY ordinal_position  # 按字段顺序排序
            """
    # 执行sql语句
    cursor.execute(sql, (dbName, tableName))
    result=cursor.fetchall()
    return result


def getAllCloumnsName(result):
    cloumnName=map(lambda x:x['COLUMN_NAME'],result)
    list1=list(cloumnName)
    #print(list1)
    return ",".join(list1)

def getAllClumnsNameAndType(result):
    # 获取列的名字和类型
    mappings = {
        'bigint': 'bigint',
        'varchar': 'string',
        'int': 'int',
        'datetime': 'string',
        'text': 'string',
        'decimal': 'string',
        'date': 'string',
        'timestamp': 'string',
        'varbinary': 'Bytes',
        'double': 'double',
        'time': 'Date'
    }

    list2=list(map(lambda x:{"name":x['COLUMN_NAME'],"type":mappings.get(x['DATA_TYPE'],'string')},result))
    return list2



if __name__ == '__main__':

    # 校验外部参数
    if len(sys.argv) != 3:
        print("请传入数据库的名字和表的名字")

    dbName = sys.argv[1]
    tableName = sys.argv[2]
    result=getDBData(dbName,tableName)
    print(result)
    cloumn=getAllCloumnsName(result)
    print(cloumn)

    columnAndType=getAllClumnsNameAndType(result)

    # 拼接json 数据
    jsonData = {
        "job": {
            "setting": {
                "speed": {
                    "channel": 3
                },
                "errorLimit": {
                    "record": 0,
                    "percentage": 0.02
                }
            },
            "content": [
                {
                    "reader": {
                        "name": "mysqlreader",
                        "parameter": {
                            "username": "root",
                            "password": "123456",
                            "connection": [
                                {
                                    "querySql": [
                                        f"select {cloumn} from {tableName}"
                                    ],
                                    "jdbcUrl": [
                                        f"jdbc:mysql://bigdata01:3306/{dbName}"
                                    ]
                                }
                            ]
                        }
                    },
                    "writer": {
                        "name": "hdfswriter",
                        "parameter": {
                            "defaultFS": "hdfs://bigdata01:9820",
                            "fileType": "text",
                            "path": f"/user/hive/warehouse/finance.db/ods_jrxd_{tableName}",
                            "fileName": f"{tableName}",
                            "writeMode": "append",
                            "column":
                                columnAndType
                            ,
                            "fieldDelimiter": ","
                        }
                    }
                }
            ]
        }
    }
    print(jsonData)
    with open(f"./datax_json/{tableName}.json", "w") as f:
        json.dump(jsonData, f)

运行上述python脚本

复制代码
python AutoCreateJson.py jrxd channel_info

根据以上写法,我还要执行 20 次脚本,很累,耽误打游戏,于是编写了一个一 键 生成所有表的json的脚本:

在 /home/scripts 文件夹

bash 复制代码
#/bin/bash
while read x1
do
    python AutoCreateJson.py jrxd $x1
done  < /root/tables.txt
bash 复制代码
chmod 777 create_datax_json.sh

将AutoCreateJson.py 也放入到/home/scripts
创建一个文件夹 mkdir -p /home/scripts/datax_json
继续执行 脚本 ./create_datax_json.sh

成功如下图所示:

四、datax 导入业务库数据到ODS层

使用 AI 帮我们编写一个脚本:

提示词:

你是一个 shell 脚本高手,目前我的文件夹/home/scripts/datax_json 下有很多的 json 文件,编写一个脚本,获取该文件夹下的所有文件,并循环执行 datax.py 文件名 这样的命令

run_all_datax.sh

bash 复制代码
#!/bin/bash

# 定义 JSON 文件所在目录
JSON_DIR="/home/scripts/datax_json"

# 定义 datax.py 的路径(请根据你实际路径修改!)
DATAX_PY="/opt/installs/datax/bin/datax.py"


echo "========================================"
echo "开始执行目录下所有 DataX 任务:$JSON_DIR"
echo "========================================"

# 循环遍历所有 .json 文件
for json_file in "$JSON_DIR"/*.json; do
    # 如果目录里没有 json 文件,跳过
    [ -e "$json_file" ] || continue
    
    echo ""
    echo "====> 正在执行:$json_file"
    
    # 执行 DataX 命令
    python "$DATAX_PY" "$json_file"
    
    
done

echo "========================================"
echo "所有任务执行完成!"
echo "========================================"
复制代码
chmod 777 run_all_datax.sh

因为我们之前已经测试过  channel_info 这个json文件了,所以为了防止数据插入重复,将该   文件删除
执行 脚本:
./run_all_datax.sh
相关推荐
回到原点的码农11 分钟前
Linux(CentOS)安装 MySQL
linux·mysql·centos
m0_4912670015 分钟前
Docker部署MySQL 多库自动备份(结构+数据完整,适配CentOS)
mysql·安全
高梦轩17 分钟前
MySQL 故障排查与优化
数据库·mysql
吴声子夜歌33 分钟前
Node.js——操作MySQL数据库
数据库·mysql·node.js
爱丽_34 分钟前
MySQL 锁等待与死锁进阶:怎么看等待、怎么降冲突(工程化套路)
数据库·mysql
心有—林夕44 分钟前
MySQL 误操作恢复完全指南
android·数据库·mysql
夕除1 小时前
Mysql--15
java·数据库·mysql
野生技术架构师1 小时前
掌握SQL窗口函数,轻松处理复杂数据分析
数据库·sql·数据分析
会飞的大可1 小时前
NoSQL:从原理到实践的全景指南
数据库·nosql
刘~浪地球2 小时前
Redis 从入门到精通(四):字符串操作详解
数据库·redis·缓存