高效的 Python Web 开发与数据库操作:基于 FastAPI 的实战与优化

高效的 Python Web 开发与数据库操作:基于 FastAPI 的实战与优化

目录

  • 🐍 1. 数据库连接池的使用与管理
  • 🔄 2. 数据库事务的处理与控制
  • 💡 3. FastAPI 中的 ORM 集成与优化

🐍 1. 数据库连接池的使用与管理

数据库连接池是 Web 应用中不可或缺的一部分,尤其是在处理高并发请求时,它能够有效地提升应用的性能。FastAPI 提供了与数据库交互的基础设施,并且与常见的数据库库(如 SQLAlchemy 和 Tortoise ORM)兼容,可以轻松实现数据库连接池的管理。连接池的核心作用是复用数据库连接,从而避免了每次请求都重新建立连接的开销。

连接池的基本概念与工作原理

在没有连接池的情况下,每次 Web 应用与数据库交互时,都需要建立与数据库的连接,这对于高并发的 Web 应用来说,会导致连接数迅速增加,进而造成数据库的压力,甚至可能导致服务崩溃。连接池的作用正是通过预先建立一定数量的数据库连接并保存在池中,确保每次请求时可以从池中获取一个空闲连接,减少了频繁建立连接的开销。

FastAPI 本身并没有直接提供连接池的实现,但可以结合 SQLAlchemy 或 Tortoise ORM 来实现连接池功能。以下是使用 SQLAlchemy 配合 asyncpgdatabases 库的连接池实现。

使用 SQLAlchemy 配合 databases 库的连接池

from databases import Database
from sqlalchemy import create_engine, MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import asyncio# 数据库配置
DATABASE_URL = "postgresql://user:password@localhost/dbname"# 创建数据库对象
database = Database(DATABASE_URL)
metadata = MetaData()# 连接池配置(通过 databases 库)
database = Database(DATABASE_URL, min_size=5, max_size=10)# 异步获取连接
async def get_db():async with database.transaction():yield database# SQLAlchemy Base
Base = declarative_base(metadata=metadata)# 连接池初始化
async def init_db():await database.connect()# 关闭连接池
async def close_db():await database.disconnect()

在这段代码中,Database 类用于创建连接池,通过传入数据库 URL 来初始化数据库连接。min_sizemax_size 分别代表连接池中最小和最大连接数。当数据库连接被请求时,连接池会分配一个空闲的连接,确保高效的数据库交互。

连接池的管理

在实际生产环境中,数据库连接池的管理至关重要,尤其是在连接数较大或应用负载较高的情况下。连接池需要确保每个数据库连接的生命周期不会超过一定的限制,防止连接泄露。通常可以通过设置连接池的最大空闲时间、最大连接数等参数来进行优化。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker# 创建引擎并启用连接池
engine = create_engine(DATABASE_URL,pool_size=10,           # 连接池中保留的连接数量max_overflow=20,        # 最大溢出连接数pool_timeout=30,        # 获取连接的超时时间pool_recycle=3600,      # 连接池中连接的最大生命周期
)SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)# 获取数据库会话
def get_db():db = SessionLocal()try:yield dbfinally:db.close()

通过以上设置,SQLAlchemy 的连接池会根据实际需要动态调整连接的数量,最大化减少因频繁创建新连接带来的性能问题。

🔄 2. 数据库事务的处理与控制

在 Web 应用中,数据库事务是保证数据一致性和完整性的关键。事务确保了一系列数据库操作要么全部成功,要么全部失败,避免了因部分操作失败而导致数据不一致的情况。在 FastAPI 中,事务管理通常与 SQLAlchemy 或 Tortoise ORM 配合使用,可以通过显式的提交和回滚操作来确保事务的正确性。

事务的基本操作

数据库事务主要包括三个步骤:开始事务、提交事务和回滚事务。在 FastAPI 中,事务的管理通常与数据库会话(Session)结合使用,SQLAlchemy 提供了方便的 API 来控制事务。

以下是使用 SQLAlchemy 进行事务管理的代码示例:

from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyErrordef create_item(db: Session, item_data: dict):# 开始一个新的事务try:item = Item(**item_data)  # 创建一个新的模型实例db.add(item)db.commit()  # 提交事务,保存数据db.refresh(item)  # 刷新对象,获取数据库中的最新值return itemexcept SQLAlchemyError as e:db.rollback()  # 如果发生错误,回滚事务raise Exception("Database operation failed") from e

在上面的代码中,db.commit() 用于提交事务,而 db.rollback() 用于回滚事务。当发生异常时,数据库操作将被撤销,确保数据的一致性。

事务中的异常处理

事务管理中最常见的问题之一是如何处理异常。对于数据库操作来说,如果某一步骤失败,必须确保前面的所有操作都被撤销,从而避免部分数据更新的情况。使用 try...except 语句来捕获和处理数据库操作中的异常是非常重要的。

from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityErrordef update_item(db: Session, item_id: int, update_data: dict):try:item = db.query(Item).filter(Item.id == item_id).first()if not item:raise ValueError("Item not found")for key, value in update_data.items():setattr(item, key, value)db.commit()db.refresh(item)return itemexcept IntegrityError as e:db.rollback()  # 违反约束时回滚raise Exception("Integrity error occurred") from eexcept Exception as e:db.rollback()  # 其他异常时回滚raise Exception("An error occurred while updating the item") from e

通过 IntegrityError 处理数据库约束错误,保证数据的完整性和一致性。而一般的异常则使用 Exception 来捕获,以确保事务的回滚。

事务的优化

在高并发环境下,数据库事务的性能至关重要。FastAPI 中的异步功能可以在处理大量并发请求时有效减少事务操作的瓶颈。通过 asyncawait 的协程机制,可以实现数据库操作的非阻塞执行,提升应用的响应速度。

from databases import Database# 异步提交事务
async def create_item(db: Database, item_data: dict):query = items.insert().values(item_data)await db.execute(query)  # 执行异步数据库操作

异步数据库操作可以显著提高应用的吞吐量,尤其是在需要进行大量数据库查询的场景中。

💡 3. FastAPI 中的 ORM 集成与优化

在 FastAPI 中,ORM(对象关系映射)使得数据库操作变得更加简洁和直观。通过使用 SQLAlchemy、Tortoise ORM 或其他 ORM 库,开发者可以避免直接编写 SQL 查询语句,从而提高开发效率。

ORM 的集成与使用

FastAPI 支持多种 ORM 库,最常用的是 SQLAlchemy 和 Tortoise ORM。通过 ORM,我们可以将数据库中的表映射为 Python 类,简化了数据库操作的过程。

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationshipclass Item(Base):__tablename__ = "items"id = Column(Integer, primary_key=True, index=True)name = Column(String, index=True)description = Column(String, index=True)

在这个例子中,Item 类代表数据库中的一个表,namedescription 字段对应表中的列。通过 SQLAlchemy 提供的 Base 类,开发者能够轻松创建与数据库表相对应的 Python 类。

ORM 性能优化

ORM 提供了更高的抽象层,但也可能带来性能瓶颈。为了避免不必要的性能损失,可以在查询时使用优化技巧,如延迟加载、选择性查询等。

# 使用 selectinload 来优化关联查询
from sqlalchemy.orm import selectinloaddef get_items_with_details(db: Session, skip: int = 0, limit: int = 10):return db.query(Item).options(selectinload(Item.details)).offset(skip).limit(limit).all()

通过 selectinload,可以优化关联查询,减少数据库的查询次数,从而提升性能。


通过连接池的有效使用、事务

管理的优化以及 ORM 的合理集成,可以大幅提升 FastAPI Web 应用的数据库操作性能。以上内容提供了基础的操作流程和最佳实践,帮助开发者构建高效、稳定的数据库交互层。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/63642.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

D3实现站点路线图demo分享

分享一下通过D3实现的站点路线分布图&#xff0c;这是一个demo。效果图如下&#xff1a; 源码如下&#xff1a; <template><div class"map-test" ref"d3Chart"><div class"tooltip" id"popup-element"><span>…

CTF-WEB: 配置一个Ubuntu 多版本php服务器

今天复现题windows的php /tmp缓存一直是空的,直接配一个新虚拟机 开始 准备一个全新的虚拟机,可以在这里下载镜像 Verifying - USTC Mirrors 走完常规安装流程继续 设置中文(可选) sudo apt install language-pack-zh-hans language-pack-gnome-zh-hans然后在设置->语…

python爬虫--小白篇【爬虫实践】

一、前言 1.1、王者荣耀皮肤爬虫 根据王者荣耀链接&#xff0c;将王者荣耀的全部英雄的全部皮肤图片爬取保存到本地。经过分析得到任务的三个步骤&#xff1a; 根据首页全部英雄列表连接获取全部英雄的名称hero_name以及对应的hero_id&#xff1b;根据单个英雄的hero_name和h…

算法日记 42 day 图论

今天来看看广度优先搜索&#xff0c;并且写几个题。刷到这里我才想起来&#xff0c;当时第一次面试的时候问的就是这个题&#xff0c;当时大概知道一点思路&#xff0c;但不清楚是图论方面的&#xff0c;更别说写出来了。 广度优先搜索&#xff08;BFS&#xff09; 不同于深度…

【NLP 13、实践 ② 判断文本中是否有特定字符出现】

人活着就是为了救赎自己&#xff1b;为了经历世间的美好&#xff1b;为了在挫折中成长变得更坚强 —— 24.12.10 一、定义模型 1.嵌入层 nn.Embedding&#xff1a;将离散值转化为向量 # embedding层&#xff0c;vocab&#xff1a;词表&#xff0c;要多少个数据&#xff08;向…

软件注册机 | QT给自己的桌面软件实现软件注册码功能

之前做的一个项目&#xff0c;想要给软件做一个注册码功能。当软件发布之后&#xff0c;不想给所有人用&#xff0c;这时就可以通过注册机给软件生成授权码来软件加密。整个过程实现分为两大步骤&#xff0c;一是在自己的软件打开时&#xff0c;增加一段判断逻辑&#xff1b;二…

GD32中断

1.什么是中断&#xff1a;打断现在正在做的事&#xff0c;去执行其他事。 2.ARM异常中断结构 3.中断向量编号。中断向量是 进行了映射的&#xff0c;直接映射到 flash中的地址。 4.中断执行结构。向量里面保存的是执行函数的地址。&#xff08;具体可在编译完后的map文件中查看…

三菱FX3U模拟量产品的介绍

FX3u可编程控制器模拟量产品包括&#xff1a;特殊适配器、特殊功能模块的连接 1、连接在FX3U可编程控制器的左侧。 2、连接特殊适配器时&#xff0c;需要功能扩展板。 3、最多可以连接4台模拟量特殊适配器。 4、使用高速输入输出特殊适配器时&#xff0c;请将模拟量特殊适配器连…

WHAT - webpack、vite(rollup)、rsbuild 对比

目录 一、分析二、其他阅读 一、分析 以下是 Webpack、Vite 和 rsbuild 在多个维度上的比较分析表格&#xff1a; 维度WebpackVitersbuild核心语言/技术使用 JavaScript 和 Node.js基于 JavaScript/TypeScript&#xff0c;依赖原生 ESM 和浏览器支持使用 Rust 编写&#xff0…

软件测试丨Appium 源码分析与定制

在本文中&#xff0c;我们将深入Appium的源码&#xff0c;探索它的底层架构、定制化使用方法和给软件测试带来的优势。我们将详细介绍这些技术如何解决实际问题&#xff0c;并与大家分享一些实用的案例&#xff0c;以帮助读者更好地理解和应用这一技术。 Appium简介 什么是App…

【PlantUML系列】流程图(四)

目录 目录 一、基础用法 1.1 开始和结束 1.2 操作步骤 1.3 条件判断 1.4 并行处理 1.5 循环 1.6 分区 1.7 泳道 一、基础用法 1.1 开始和结束 开始一般使用start关键字&#xff1b;结束一般使用stop/end关键字。基础用法包括&#xff1a; start ... stopstart ...…

Linux 串口编程

目录 前言一、tty体系二、串口硬件基础知识三、Linux下的串口编程3.1 打开串口3.2 从串口读写数据,问题1、2的诞生3.3 关闭串口3.4 串口配置3.4.1 获取/设置串口的参数3.4.2 设置波特率3.4.3 设置控制模式标志3.4.4 设置本地模式标志3.4.5 设置输入模式标志3.4.6 设置输出模式标…

️【设计模式】之单例模式详解:创建者模式中的一颗“明珠”

全文目录&#xff1a; 开篇语&#x1f3af; 什么是单例模式&#xff1f;&#x1f5c2;️ 单例模式的关键特性&#x1f511; 单例模式的实现方式1. &#x1f331; 懒汉式单例&#xff08;Lazy Initialization&#xff09;2. &#x1f512; 懒汉式单例&#xff08;线程安全版&…

idea压缩js,css

这是需要的jar包(文章顶部也可以下载) 地址:https://download.csdn.net/download/yuzheh521/90109966?spm1001.2101.3001.9500 压缩js arguments: -jar E:\swj\jar_packages\css_js_compress\yuicompressor-2.4.8.jar --type js --charset utf-8 $FilePath$ -o $FileNameWith…

ASP.NET |日常开发中连接Oracle数据库详解

ASP.NET &#xff5c;日常开发中连接Oracle数据库详解 前言一、安装和配置 Oracle 数据访问组件1.1 安装ODP.NET&#xff08;Oracle Data Provider for.NET&#xff09;&#xff1a;1.2 引用相关程序集&#xff1a; 二、配置连接字符串2.1 连接字符串的基本组成部分&#xff1a…

【linux系统】基础开发工具(yum、Vim)

1. 软件包管理器 1.1 什么是软件包 在Linux下安装软件, ⼀个通常的办法是下载到程序的源代码, 并进⾏编译, 得到可执⾏程序. 但是这样太麻烦了, 于是有些⼈把⼀些常⽤的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在⼀个服务器上, 通过包管理器可以很⽅便的…

C语言:define定义常量和定义宏(详解)

本篇博客给大家带来的是#define定义常量和#define定义宏的方法 &#x1f41f;&#x1f41f;文章专栏&#xff1a;C语言 &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢迎大家点赞、收藏、分享 你们的支持就是我创造的动力 今日思想&#xff1…

Let up bring up a linux.part2 [十一]

之前的篇幅中我们已经将 Linux 内核 bringup 起来了&#xff0c;不知道大家有没有去尝试将根文件系统运行起来&#xff0c;今天我就带领大家完成这个事情&#xff0c;可以跟着下面的步骤一步步来完成&#xff1a; 在这里我们使用 busybox 构建 rootfs&#xff1a; 下载 busyb…

使用GO--Swagger生成文档

概述 在前后端分离的项目中&#xff0c;后端配置swagger可以很好的帮助前端人员了解后端接口参数和数据传输。go-swagger 是一个功能全面且高性能的Go语言实现工具包&#xff0c;用于处理Swagger 2.0&#xff08;即OpenAPI 2.0&#xff09;规范。它提供了丰富的工具集&#x…

pushgateway HA高可用方案

未经本人同意不得转载&#xff0c;若引用请附上原文链接。 项目使用flink来处理kafka中的无界流数据&#xff0c;采用的是flink on yarn的模式部署flink任务。最近做flink任务的监控过程中&#xff0c;踩了一些坑。下面是过程&#xff0c;只想看最终方案的直接拉到最后。 先说…