Python 如何处理数据库事务

Python 如何处理数据库事务

数据库事务是指一组操作要么全部执行成功,要么全部回滚的过程。事务是确保数据库一致性的重要手段,特别是在处理需要多步操作的场景时,能够避免部分数据成功更新而部分数据失败的情况。本文将详细介绍什么是数据库事务,以及如何在 Python 中通过各种方式(例如,使用 sqlite3MySQLPostgreSQL 等数据库驱动)处理事务。

在这里插入图片描述

什么是数据库事务?

1. 事务的概念

数据库事务(transaction)是指一组操作,它们被看作是一个单一的逻辑单元,要么全部执行成功,要么全部执行失败。事务具有以下四个特性,简称为 ACID 特性:

  • 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败并回滚。事务不能处于部分成功、部分失败的状态。
  • 一致性(Consistency):事务开始前和结束后,数据库的状态必须保持一致,任何违反数据库规则的操作都不能提交。
  • 隔离性(Isolation):事务之间彼此独立执行,事务的中间状态对于其他事务是不可见的。
  • 持久性(Durability):事务一旦提交,数据将被持久保存,即使发生系统故障也不会丢失。

2. 为什么需要事务?

事务对于保证数据库操作的可靠性和数据的一致性至关重要。以下是几个常见的使用场景:

  • 多步骤的操作:比如,在电商平台中,用户购买商品时,涉及到扣除库存、创建订单和扣减用户账户余额等操作,这些操作必须作为一个整体来执行。如果其中某一个步骤失败,则需要回滚所有已经完成的步骤,确保系统数据不会不一致。
  • 防止部分更新:在同一个操作中,假设有多个更新操作,一旦其中某个操作失败,应该取消其他操作的影响,保证数据库不会处于不完整的更新状态。
  • 并发控制:多个事务同时进行时,事务的隔离性可以避免脏读、不可重复读和幻读等问题。

在 Python 中处理事务

在 Python 中处理数据库事务通常涉及使用数据库驱动(如 sqlite3psycopg2PyMySQL 等),这些驱动通常提供内置的事务管理功能。以下是一些常见数据库库和事务管理的示例。

1. 使用 SQLite 处理事务

SQLite 是一个轻量级的数据库,广泛用于小型应用和开发环境中。在 Python 中,sqlite3 模块提供了事务支持。

事务的基本操作

sqlite3 默认是在“自动提交”模式下运行的,这意味着每个 SQL 语句都是一个事务。但是,你可以手动控制事务的开始和提交。

import sqlite3# 连接到数据库
conn = sqlite3.connect('example.db')try:# 创建游标cursor = conn.cursor()# 开始事务(默认自动开始,显示调用 conn.commit() 或 conn.rollback() 来结束)cursor.execute("BEGIN")# 执行多个 SQL 语句cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Alice", 30))cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1")# 提交事务conn.commit()
except Exception as e:# 出现错误时回滚事务conn.rollback()print(f"Transaction failed: {e}")
finally:# 关闭连接conn.close()

在这个例子中,我们执行了两条 SQL 语句——插入用户数据和更新账户余额。这两条语句被视为一个事务,只有当两者都成功时,才会提交到数据库。一旦其中任何一个操作失败,事务将回滚,取消已完成的操作。

自动提交模式

sqlite3 中,如果不手动控制事务,它将处于自动提交模式。这意味着每条 SQL 语句执行后都会立即提交。

如果你需要在同一个连接中执行多条语句并确保它们作为一个事务执行,则需要手动控制事务,使用 conn.commit()conn.rollback()

2. 使用 MySQL 处理事务

在 MySQL 中,我们可以使用 PyMySQLMySQL Connector/Python 等库来处理事务。

使用 PyMySQL 处理事务
import pymysql# 连接到 MySQL 数据库
conn = pymysql.connect(host='localhost',user='root',password='password',db='test_db'
)try:# 创建游标cursor = conn.cursor()# 执行多个 SQL 语句cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Bob", 25))cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE user_id = 2")# 提交事务conn.commit()
except Exception as e:# 如果有任何错误,回滚事务conn.rollback()print(f"Transaction failed: {e}")
finally:# 关闭连接conn.close()

在 PyMySQL 中,默认情况下事务是手动控制的。在执行完一组操作后,使用 conn.commit() 提交事务;如果发生错误,则使用 conn.rollback() 回滚事务。

使用 MySQL Connector/Python 处理事务

MySQL Connector 是 MySQL 官方提供的 Python 库。事务操作与 PyMySQL 类似。

import mysql.connector# 连接到数据库
conn = mysql.connector.connect(host='localhost',user='root',password='password',database='test_db'
)try:cursor = conn.cursor()# 执行多条 SQL 语句cursor.execute("INSERT INTO orders (order_id, user_id) VALUES (%s, %s)", (101, 1))cursor.execute("UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 1")# 提交事务conn.commit()
except Exception as e:# 回滚事务conn.rollback()print(f"Transaction failed: {e}")
finally:conn.close()

在 MySQL 中,事务控制的基本步骤与 PyMySQL 类似,都是先执行 SQL 操作,然后手动提交或回滚事务。

3. 使用 PostgreSQL 处理事务

PostgreSQL 是一个功能强大的开源数据库,支持丰富的事务功能。在 Python 中,psycopg2 是最常用的与 PostgreSQL 交互的库。

使用 psycopg2 处理事务
import psycopg2# 连接到 PostgreSQL 数据库
conn = psycopg2.connect(dbname="test_db",user="user",password="password",host="localhost"
)try:cursor = conn.cursor()# 执行 SQL 操作cursor.execute("INSERT INTO employees (name, department) VALUES (%s, %s)", ("John", "HR"))cursor.execute("UPDATE payroll SET salary = salary + 500 WHERE employee_id = 3")# 提交事务conn.commit()
except Exception as e:# 事务失败时回滚conn.rollback()print(f"Transaction failed: {e}")
finally:conn.close()

psycopg2 中的事务处理也是手动控制的,事务的提交和回滚需要明确调用 conn.commit()conn.rollback()

4. Django 中的事务处理

如果你使用的是 Django 这种高级 Web 框架,事务管理会更加简洁。Django 自带事务管理功能,并且有两种主要的事务处理方式:自动管理和手动管理。

自动事务管理

在 Django 中,默认情况下,所有的数据库操作都在自动提交模式下运行。每次数据库操作都会立即提交。

手动事务管理

对于更复杂的事务,Django 提供了 transaction.atomic() 这个上下文管理器,允许你手动控制事务。

from django.db import transactiontry:with transaction.atomic():user = User.objects.create(username="alice")Account.objects.create(user=user, balance=1000)
except Exception as e:print(f"Transaction failed: {e}")

在这个示例中,transaction.atomic() 将确保 UserAccount 的创建操作作为一个原子操作。如果任何一个操作失败,整个事务将回滚。

5. SQLAlchemy 中的事务处理

如果你使用 ORM 库如 SQLAlchemy,事务管理也是非常简洁的。SQLAlchemy 允许你在会话(session)级别管理事务。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import User, Account  # 假设已经定义了 ORM 模型# 连接数据库
engine = create_engine('sqlite:///example.db')
Session = sessionmaker(bind=engine)
session = Session()try:# 创建用户和账户new_user = User(name="Alice")session.add(new_user)new_account = Account(user=new_user, balance=1000)session.add(new_account)# 提交事务session.commit()
except Exception as e:# 事务回滚session.rollback()print(f"Transaction failed: {e}")
finally:session.close()

SQLAlchemy 提供了与数据库会话绑定的事务管理,确保所有操作作为一个事务执行。

事务处理中的常见问题

1. 并发事务问题

在多用户同时操作数据库时,可能会出现并发事务的问题。常见的并发问题有:

  • 脏读(Dirty Read):一个事务读取到另一个事务未提交的数据。
  • 不可重复读(Non-repeatable Read):在一个事务中,两次读取同一数据,得到的结果不同。
  • 幻读(Phantom Read):在一个事务中,读取相同条件的数据两次,得到的行数不同。

为了解决这些问题,数据库提供了不同的隔离级别,如:

  1. Read Uncommitted:允许脏读。
  2. Read Committed:只允许读取已提交的事务数据。
  3. Repeatable Read:防止不可重复读。
  4. Serializable:防止幻读,保证事务串行执行。

不同数据库对隔离级别的实现有所不同,开发者应根据具体应用场景选择合适的隔离级别。

2. 死锁问题

死锁是指两个或多个事务互相等待对方持有的资源,导致系统无法继续执行。为了解决死锁问题,数据库通常会有自动检测和解除死锁的机制,开发者也可以通过减少锁的持有时间和访问顺序来避免死锁。

总结

事务是确保数据库一致性和可靠性的关键机制。在 Python 中,无论是使用原生的数据库驱动,还是使用 ORM 工具如 Django 和 SQLAlchemy,都可以方便地管理数据库事务。开发者需要根据实际需求,选择合适的事务管理方式,避免常见的并发问题和死锁问题。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

关于Amazon Linux 2023的版本及包管理器

在亚马逊上创建EC2实例时,会看到有一个Amazon Linux镜像。 那这个镜像与其他Linux有什么关系和区别呢? 网站是介绍:Amazon Linux 2023 是基于 Linux 的现代化通用操作系统,提供 5 年的长期支持。它针对 AWS 进行了优化&#xff0…

【Python】 列表解析 语法 实例展示 说明统统一顿明白!!!

列表解析 根据已有列表,高效创建新列表的方式。 列表解析是Python迭代机制的一种应用,它常用于实现创建新的列表,因此用在[]中。 语法: [expression for iter_val in iterable] [expression for iter_val in iterable if con…

代码注释,是程序员的美德还是无能的表现?

前言 嗨,大家好! 今天咱们来聊聊一个老生常谈但又永远不过时的话题 —— 代码注释。 你是不是也经历过这样的时刻:打开一段陌生的代码,就像进入了迷宫一样找不到北?这时候,一个好的注释简直就是你的指路…

飞机大战ai通过dqn实现

借鉴 飞机大战源码 github 王者荣耀ai训练(试了一下,发现电脑带不动,就改了一点,训练其他游戏) 源码 通过网盘分享的文件:PlaneWar (2).zip [链接](https://pan.baidu.com/s/1N4OorR7b36Zml8MadGmI6g?pwd1234&#xf…

第十六章 RabbitMQ延迟消息之延迟插件优化

目录 一、引言 二、优化方案 三、核心代码实现 3.1. 生产者代码 3.2. 消息处理器 3.3. 自定义多延迟消息封装类 3.4. 订单实体类 3.5. 消费者代码 四、运行效果 一、引言 上一章节我们提到,直接使用延迟插件,创建一个延迟指定时间的消息&…

晶体匹配测试介绍

一、晶体参数介绍 晶体的电气规格相对比较简单,如下: 我们逐一看看每个参数, FL就是晶体的振动频率,这个晶体是24.576MHz的。 CL就是负载电容,决定了晶体频率是否准确,包括外接的实际电容、芯片的等效电容以及PCB走线的寄生电容等,核心参数。 Frequency Tolerance是…

堆排序(C++实现)

参考: 面试官:请写一个堆排序_哔哩哔哩_bilibiliC实现排序算法_c从小到大排序-CSDN博客 堆的基本概念 堆排实际上是利用堆的性质来进行排序。堆可以看做一颗完全二叉树。 堆分为两类: 最大堆(大顶堆):除根…

Deep tone mapping network in HSV color space

Abstract 色调映射算子可以将高动态范围(HDR)图像转换为低动态范围(LDR)图像,这样我们就可以用LDR设备享受HDR图像的信息内容。然而,目前的色调映射算法主要关注亮度映射,而忽略了颜色分量。与此同时,它们经常遭受光晕伪影和过度…

IaaS,PaaS和SaaS的区别讲解

IaaS、PaaS和SaaS有什么区别吗?这三个概念非常简单。 只不过在说它们仨的区别前,有个常识需要知道一下: 我们传统开发一个软件,需要9个东西: 作为使用软件的人,左边的【应用】和【数据】,是离…

Django的请求与响应

Django的请求与响应 1、常见的请求2、常见的响应3、案例 1、常见的请求 函数的参数request是一个对象,封装了用户发送过来的所有请求相关数据。 get请求一般用来请求获取数据,get请求也可以传参到后台,但是传递的参数显示在地址栏。 post请求…

企业内部文档安全外发如何挑选合适的外发系统?

企业文档的外发不仅关系到运营效率,更是信息安全的重要组成部分。面对B2B模式下文档交换的普遍性和重要性,企业内部文档的安全外发成为了众多公司关注的重点之一。 随着互联网技术的发展,企业之间的合作越来越紧密,文档的交流也变…

Java Agent 技术解析

什么是Java Agent Java Agent是在 JDK1.5 引入的一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行,在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功…

第十四章:收尾过程组(14.1结束项目或阶段--14.2收尾过程组重点工作)

14.1 结束项目或阶段 过程定义:终结项目、阶段或合同的所有活动的过程 14.1.1 主要输入 1.项自章程 项目章程记录了项目成功标准、审批要求,以及由谁来签署项目结束 2.项目管理计划 项目管理计划的所有组成部分均为结束项目或阶段过程的输入。 3.项…

【视觉分割新SOTA|论文解读1】一种最先进的图像分割模型——Segment Anything Model (SAM)

【视觉分割新SOTA|论文解读1】一种最先进的图像分割模型——Segment Anything Model (SAM) 【视觉分割新SOTA|论文解读1】一种最先进的图像分割模型——Segment Anything Model (SAM) 文章目录 【视觉分割新SOTA|论文解读1】一种最先进的图像分割模型——Segment Anything Mod…

全院级、流程化的医院安全不良事件管理系统源码——等级医院评审工作的辅助工具

前言: 冰山理论”指出“每件严重不良事件背后可能隐藏着10件轻微的不良事件”“存在30件未造成伤害的差错可能存在600件引发意外的异常事件”没有一件不良事件应该被忽视! 一项研究也指出95%医生曾目睹错误的发生,61%的医务人员认为医疗错误…

基于Python星载气溶胶数据处理与反演分析技术

MODIS(中分辨率成像光谱仪)和CALIOP(云-气溶胶偏振激光雷达)是两种重要的星载遥感观测平台,它们提供了大量的气溶胶数据。MODIS通过成像光谱技术获取不同波长的遥感数据,从而得到气溶胶的空间分布、光学厚度…

耳夹式耳机哪个最好?2024年五大热门耳夹式耳机品牌分享

耳夹式耳机哪个最好?2024年五大热门耳夹式耳机品牌分享 耳夹式蓝牙耳机怎样才算好、算优质呢?哪款比较好呢?对于第一个问题,我认为耳夹式蓝牙耳机得具备以下几个特征优势才称得上是优质产品。其一,要能提供清晰、平衡…

nuxtjs使用rem 实现自适应窗口的大小

效果图: 步骤 1:安装 PostCSS 和 PostCSS 插件 npm install postcss postcss-pxtorem --save-dev步骤 2:配置 nuxt.config.ts // nuxt.config.ts export default defineNuxtConfig({compatibilityDate: 2024-04-03,devtools: { enabled: …

本地windows文件上传到远程阿里云windows server方法

一.功能简介 在本地windows下开发完成软件后,需要上传到远程阿里云服务器进行发布,可使用该方法,快速实现本地文件上传。 二.方法 在本地windows系统使用快捷键 winR,打开运行对话框,‌通过这个对话框,用…

解决Windows Server 2016本地登录失败但远程登录正常的问题:排查与解决方案

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…