SQLAlchemy编写的MySQL数据库迁移至金仓数据库

 更新时间:2026年05月23日 08:56:36   作者:码农阿豪@新空间  
该文章详细记录将一个使用SQLAlchemy编写的MySQL数据库迁移至金仓数据库的过程,主要步骤包括安装SQLAlchemy、安装金仓方言包、创建连接字符串、配置连接池、ORM建模和基本操作等,文章中提到了一些踩坑记录,如方言包的安装位置、版本匹配问题、连接字符串的书写方式等

从一个报错开始

上周接了个小活,要把一个用SQLAlchemy写的数据分析脚本从MySQL迁到金仓。本来以为换个数据库驱动就行,结果跑起来直接报错:No module named 'sqlalchemy.dialects.kingbase'

查了一圈才发现,SQLAlchemy不像MySQL、PostgreSQL那样自带驱动,金仓的方言包需要手动装。折腾了两天才跑通,今天把过程记下来,希望能帮到遇到同样问题的人。

一、方言包是什么,为什么非要手动装

SQLAlchemy本身只是个壳,它不知道自己该怎么跟数据库说话。每种数据库需要一个“翻译”,这个翻译就叫方言包(dialect)。

MySQL、PostgreSQL这种主流数据库,SQLAlchemy安装的时候就把它们的方言包带上了。但金仓不在这个列表里,所以得自己去官网下,然后手动放到指定位置。

方言包底层依赖ksycopg2驱动,所以这两个都得装。

二、安装步骤(踩坑记录)

2.1 先装SQLAlchemy

pip install sqlalchemy

装完看一眼装在哪了,后面放方言包要用:

pip show sqlalchemy

我的机器输出是这样的:

Name: SQLAlchemy
Version: 1.4.36
Location: /usr/local/lib/python3.8/site-packages

记下这个Location路径。

2.2 装ksycopg2驱动

pip install ksycopg2

这个倒是顺利,没遇到什么问题。Windows用户可能需要装ksycopg2-win64

2.3 放方言包(这里卡了我半天)

找到SQLAlchemy的安装目录,进去找到dialects文件夹:

cd /usr/local/lib/python3.8/site-packages/sqlalchemy/dialects

把从官网下载的kingbase文件夹整个复制到这里。最终目录结构应该是:

sqlalchemy/dialects/
├── kingbase/
│   ├── __init__.py
│   └── base.py
├── mysql/
├── postgresql/
└── ...

我一开始放错了地方,放到了site-packages根目录下,结果死活加载不了。后来仔细看了文档才发现要放到dialects下面。

版本匹配问题:官方提供了1.3、1.4、2.0三个版本的方言包。我用的SQLAlchemy是1.4.36,选了1.4版本的方言包。版本不对会报一些奇怪的错,比如找不到某个模块。

三、连接数据库

3.1 连接字符串怎么写

折腾完安装,终于可以写代码了。连接字符串的格式是:

from sqlalchemy import create_engine

engine = create_engine('kingbase+ksycopg2://SYSTEM:123456@127.0.0.1:54321/TEST')

翻译一下:

  • kingbase:方言名,告诉SQLAlchemy用金仓的方言包
  • ksycopg2:驱动名,实际干活的是这个
  • SYSTEM:数据库用户名
  • 123456:密码
  • 127.0.0.1:IP
  • 54321:端口(金仓默认是这个)
  • TEST:数据库名

+ksycopg2其实可以省略,写成kingbase://...就行,默认就是用它。

3.2 测试一下能不能连上

from sqlalchemy import create_engine

conn_str = 'kingbase://SYSTEM:123456@127.0.0.1:54321/TEST'
engine = create_engine(conn_str)

conn = engine.connect()
result = conn.execute("SELECT version()")
print(result.fetchone())
conn.close()

如果看到版本信息输出,恭喜,连上了。

3.3 连接池参数(生产环境有用)

如果是写Web服务或者长期运行的脚本,建议配置一下连接池:

engine = create_engine(
    'kingbase://SYSTEM:123456@127.0.0.1:54321/TEST',
    pool_size=10,          # 连接池里放多少个连接
    max_overflow=20,       # 不够用时最多再创建多少个
    pool_recycle=3600,     # 连接用多久回收(秒)
    pool_pre_ping=True     # 用之前先ping一下,确认还活着
)

pool_pre_ping=True这个参数挺实用的,能避免拿到一个已经断开的连接。

四、ORM建模和基本操作

连接搞定了,接下来看看怎么用ORM操作数据库。

4.1 定义模型

先建个基类,然后定义表对应的类:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime
from datetime import datetime

Base = declarative_base()

class User(Base):
    __tablename__ = 'test_user'  # 表名
    
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    email = Column(String(100))
    created_at = Column(DateTime, default=datetime.now)
    
    def __repr__(self):
        return f"User(id={self.id}, name='{self.name}', email='{self.email}')"

__tablename__是必须的,不写SQLAlchemy不知道表叫什么。

4.2 建表

# 自动创建表(如果不存在的话)
Base.metadata.create_all(engine)

这个操作是幂等的,执行多次也不会重复建表。

4.3 创建Session

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()

4.4 增删改查

插入数据:

user1 = User(name='张三', email='zhangsan@test.com')
user2 = User(name='李四', email='lisi@test.com')

session.add(user1)
session.add(user2)
# 或者一次加多个:session.add_all([user1, user2])
session.commit()

查询数据:

# 查所有
users = session.query(User).all()
for u in users:
    print(u.name, u.email)

# 条件查询
user = session.query(User).filter(User.name == '张三').first()
print(user.email)

# 模糊查询
users = session.query(User).filter(User.name.like('%张%')).all()

更新数据:

# 方式1:查出来改属性
user = session.query(User).filter(User.name == '张三').first()
user.email = 'newemail@test.com'
session.commit()

# 方式2:批量更新(不查直接改)
session.query(User).filter(User.name == '张三').update(
    {"email": "batch_update@test.com"}
)
session.commit()

删除数据:

# 查出来删
user = session.query(User).filter(User.name == '张三').first()
session.delete(user)
session.commit()

# 批量删
session.query(User).filter(User.id > 100).delete()
session.commit()

4.5 事务处理

Session默认不会自动提交,调用commit()才真正写入。如果中间出错,可以回滚:

try:
    session.add(User(name='王五', email='wangwu@test.com'))
    # 这里如果出错...
    session.commit()
except Exception as e:
    session.rollback()
    print(f"出错了: {e}")
finally:
    session.close()

4.6 完整跑一遍

把上面的代码串起来,跑一个完整的例子:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, String

# 连数据库
engine = create_engine('kingbase://SYSTEM:123456@127.0.0.1:54321/TEST')

# 定义模型
Base = declarative_base()
class User(Base):
    __tablename__ = 'test_user'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    email = Column(String(100))
    def __repr__(self):
        return f"User(id={self.id}, name={self.name})"

# 建表
Base.metadata.create_all(engine)

# 操作
Session = sessionmaker(bind=engine)
session = Session()

# 插入
session.add_all([
    User(name='张三', email='zhangsan@test.com'),
    User(name='李四', email='lisi@test.com'),
])
session.commit()

# 查询并打印
for user in session.query(User).all():
    print(user)

session.close()

五、踩过的几个坑

坑1:方言包放错位置

这是最容易犯的错。方言包必须放在sqlalchemy/dialects/kingbase/,不是随便扔到site-packages就行。

坑2:版本不对应

SQLAlchemy 1.4的版本要用1.4的方言包。拿1.3的方言包去连1.4的SQLAlchemy,会报模块找不到的错误。

坑3:libkci.so找不到

报错信息是libkci.so: cannot open shared object file。设置一下环境变量就能解决:

export LD_LIBRARY_PATH=/home/kingbase/lib:$LD_LIBRARY_PATH

坑4:连接字符串写错

kingbase://不要写成kingbase+psycopg2://,虽然ksycopg2基于psycopg2改的,但名字写错了就是连不上。

六、小结

折腾下来,SQLAlchemy连金仓其实不算复杂,就是方言包要手动配置这一点跟其他数据库不一样。

整体流程分三步:

  1. 装SQLAlchemy和ksycopg2
  2. 把金仓方言包放到sqlalchemy/dialects/下面
  3. kingbase://开头的连接字符串创建engine

ORM操作和连其他数据库一模一样,基本不用改代码。如果项目里用SQLAlchemy做ORM,切换成本其实挺低的。

到此这篇关于SQLAlchemy编写的MySQL数据库迁移至金仓数据库的文章就介绍到这了,更多相关MySQL迁移至金仓数据库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解hive常见表结构

    详解hive常见表结构

    hive是基于Hadoop的一个数据仓库工具,用来进行数据提取、转化、加载,这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制,这篇文章主要介绍了hive常见表结构,需要的朋友可以参考下
    2022-08-08
  • 关于ADOX的相关知识

    关于ADOX的相关知识

    关于ADOX的相关知识...
    2006-12-12
  • Spring集成MyBatis完整实例(分享)

    Spring集成MyBatis完整实例(分享)

    下面小编就为大家带来一篇Spring集成MyBatis完整实例(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • SQL 随机查询 包括(sqlserver,mysql,access等)

    SQL 随机查询 包括(sqlserver,mysql,access等)

    SQL 随机查询 包括(sqlserver,mysql,access等),需要的朋友可以参考下,目的一般是为了随机读取数据库中的记录。
    2009-10-10
  • 利用DataSet部分功能实现网站登录

    利用DataSet部分功能实现网站登录

    这篇文章主要介绍了利用DataSet部分功能实现网站登录 ,需要的朋友可以参考下
    2017-05-05
  • 实例介绍SQL注入以及如何解决

    实例介绍SQL注入以及如何解决

    这篇文章主要给大家介绍了关于SQL注入以及如何解决的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 动态SQL在梧桐数据库的使用方法及适应场景

    动态SQL在梧桐数据库的使用方法及适应场景

    这篇文章主要介绍了动态SQL在梧桐数据库的使用方法及适应场景,通过简单的例子展示了如何在梧桐数据库中使用动态SQL,动态SQL可以灵活处理不同量的输入参数,提升查询效率,但也会增加代码调试的难度,适用场景包括处理不确定的参数、通过输入生成其他参数以及在for循环中使用
    2024-11-11
  • windows安装Neo4j图数据库的详细过程

    windows安装Neo4j图数据库的详细过程

    本文介绍了在Windows上安装和配置Neo4j图数据库的步骤,包括安装JavaSDK、解压安装Neo4j、配置环境变量、启动数据库以及服务化启动,感兴趣的朋友一起看看吧
    2025-03-03
  • SQLSERVER 高级复 制 排错 技巧

    SQLSERVER 高级复 制 排错 技巧

    SQLSERVER 高级复 制 排错 技巧...
    2007-08-08
  • Access和SQL Server里面的SQL语句的不同之处

    Access和SQL Server里面的SQL语句的不同之处

    做了一个Winform的营养测量软件,来回的捣腾着Access数据库,还是那几句增删改查,不过用多了,发现Access数据库下的SQL语句和SQL Server下正宗的SQL还有有很大的不同。
    2009-12-12

最新评论