Python作为一门通用编程语言,其数据库访问能力经历了三个重要发展阶段。早期通过各数据库厂商提供的专用接口(如MySQLdb)进行连接,这种方式存在明显的厂商锁定问题。随着PEP 249(Python Database API Specification v2.0)的制定,Python建立了统一的数据库访问规范,这直接催生了SQLAlchemy等ORM工具的出现。发展到今天,Python已经形成了包含驱动层、抽象层和ORM层的完整数据库技术栈。
在实际工程中,我们通常会根据项目规模进行技术选型。小型项目可以直接使用psycopg2、PyMySQL这类驱动级模块;中型项目适合采用SQLAlchemy Core这类轻量级抽象层;而大型企业级应用则可能需要完整的ORM方案配合异步IO驱动。值得注意的是,随着Python类型系统的完善,现代数据库模块如SQLModel已经开始深度集成类型注解功能。
以PostgreSQL为例,psycopg2作为官方推荐驱动,其连接池管理采用绿色线程(green thread)实现。在创建连接时建议设置:
python复制conn = psycopg2.connect(
host="localhost",
database="mydb",
user="postgres",
password="secret",
connect_timeout=3,
keepalives=1
)
其中connect_timeout可避免网络问题导致的长时间阻塞,keepalives参数则维持TCP长连接。
SQLAlchemy的引擎配置更为复杂,其连接字符串支持多种方言:
python复制engine = create_engine(
"postgresql+psycopg2://user:pass@host:5432/dbname",
pool_size=5,
max_overflow=10,
pool_timeout=30,
pool_recycle=3600
)
pool_recycle参数特别重要,它定期重置连接以避免数据库端连接超时。
MongoDB的PyMongo驱动在批量操作时性能表现优异。其insert_many()方法支持有序和无序两种模式:
python复制# 无序插入更快但可能乱序
result = db.collection.insert_many(docs, ordered=False)
当处理大量文档时,建议将ordered设为False以获得更高吞吐。
Redis的redis-py模块提供了连接池和管道功能。一个典型的事务管道示例如下:
python复制with r.pipeline() as pipe:
while True:
try:
pipe.watch('key')
current_value = pipe.get('key')
pipe.multi()
pipe.set('key', int(current_value) + 1)
pipe.execute()
break
except WatchError:
continue
这种乐观锁机制可有效处理并发修改。
多对多关系需要通过关联表实现。假设有学生和课程两个模型:
python复制association_table = Table(
'association', Base.metadata,
Column('student_id', Integer, ForeignKey('students.id')),
Column('course_id', Integer, ForeignKey('courses.id'))
)
class Student(Base):
__tablename__ = 'students'
id = Column(Integer, primary_key=True)
courses = relationship("Course", secondary=association_table)
class Course(Base):
__tablename__ = 'courses'
id = Column(Integer, primary_key=True)
查询时可以使用join进行复杂关联查询:
python复制session.query(Student).join(Student.courses).filter(Course.name == 'Math')
select_related和prefetch_related是Django ORM的两大查询优化利器:
python复制# 单次SQL查询获取关联对象
books = Book.objects.select_related('author').all()
# 额外查询但更灵活
books = Book.objects.prefetch_related('tags').all()
对于大型结果集,使用iterator()方法可显著减少内存占用:
python复制for book in Book.objects.all().iterator(chunk_size=2000):
process(book)
SQLAlchemy的QueuePool默认配置可能不适合高并发场景。建议根据实际负载调整:
python复制engine = create_engine(
"postgresql://...",
pool_size=20,
max_overflow=0,
pool_pre_ping=True
)
pool_pre_ping会在每次连接使用前进行健康检查,但会带来轻微性能损耗。对于需要长时间空闲的应用,应设置pool_recycle小于数据库的wait_timeout。
参数化查询是防止SQL注入的基本要求。错误的做法:
python复制# 危险!可能被注入
cursor.execute(f"SELECT * FROM users WHERE name = '{name}'")
正确的参数化方式:
python复制# 安全
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))
在SQLAlchemy中,应始终使用text()构造带参数的查询:
python复制from sqlalchemy import text
stmt = text("SELECT * FROM users WHERE name = :name")
result = conn.execute(stmt, {"name": user_input})
asyncpg是PostgreSQL的高性能异步驱动。其连接池使用示例:
python复制pool = await asyncpg.create_pool(
user='user',
password='secret',
database='dbname',
min_size=5,
max_size=20
)
async with pool.acquire() as conn:
await conn.execute("INSERT INTO table VALUES($1)", value)
注意asyncpg使用$1、$2作为参数占位符,不同于psycopg2的%s。
SQLModel结合了Pydantic和SQLAlchemy的优点:
python复制class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
engine = create_engine("sqlite:///database.db")
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
hero = Hero(name="Spider-Man", secret_name="Peter Parker")
session.add(hero)
session.commit()
其类型注解会在运行时进行验证,有效防止数据类型错误。
Alembic是SQLAlchemy生态的标准迁移工具。典型工作流程:
bash复制# 初始化迁移环境
alembic init migrations
# 生成新迁移脚本
alembic revision --autogenerate -m "add user table"
# 执行迁移
alembic upgrade head
迁移脚本中应避免直接使用字符串拼接SQL,而是使用op命令:
python复制def upgrade():
op.create_table(
'users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
对于Django项目,其内置的migration系统更为自动化:
bash复制# 检测模型变更
python manage.py makemigrations
# 查看生成的SQL
python manage.py sqlmigrate app_name 0001
# 应用迁移
python manage.py migrate
SQLAlchemy支持绑定多个引擎实现多数据库操作:
python复制engine_read = create_engine("postgresql://read_server/db")
engine_write = create_engine("postgresql://write_server/db")
SessionRead = sessionmaker(bind=engine_read)
SessionWrite = sessionmaker(bind=engine_write)
对于水平分片场景,可以使用SQLAlchemy的horizontal sharding扩展:
python复制from sqlalchemy.ext.horizontal_shard import ShardedSession
shard_lookup = {
'shard1': create_engine("postgresql://shard1/db"),
'shard2': create_engine("postgresql://shard2/db")
}
def shard_chooser(mapper, instance, clause=None):
if instance.user_id % 2 == 0:
return 'shard1'
else:
return 'shard2'
session = ShardedSession(
shard_chooser=shard_chooser,
shards=shard_lookup
)
SQLAlchemy的事件系统可用于监控查询性能:
python复制from sqlalchemy import event
@event.listens_for(Engine, "before_cursor_execute")
def before_cursor_execute(conn, cursor, statement, parameters, context, executemany):
context._query_start_time = time.time()
@event.listens_for(Engine, "after_cursor_execute")
def after_cursor_execute(conn, cursor, statement, parameters, context, executemany):
duration = time.time() - context._query_start_time
if duration > 0.5: # 记录慢查询
logger.warning(f"Slow query: {statement} took {duration:.2f}s")
对于Django项目,可以使用django-debug-toolbar实时查看查询情况:
python复制# settings.py
DEBUG_TOOLBAR_CONFIG = {
'SQL_WARNING_THRESHOLD': 100 # 毫秒
}