从 MySQL 到 DynamoDB:一次真实项目的数据库迁移实践与性能对比
项目背景
在一个用户行为分析系统中,原有架构使用 RDS MySQL (db.r5.large) 存储操作日志。随着业务增长,写入量从每秒几十条增加到每秒数千条,MySQL 方案暴露出几个问题:
- 高峰期 CPU 持续 90%+,影响查询响应
- 扩容需要停机或切换,无法平滑应对突发流量
- 为抗住峰值需要预留大实例,平时利用率不到 10%
基于这些问题,我们评估了亚马逊云科技 DynamoDB 作为替代方案。
DynamoDB 核心特性
DynamoDB 是一个全托管的 Serverless NoSQL 数据库:
- 自动扩缩容:无需手动调整读写容量
- 按需计费(On-Demand 模式):按实际读写请求计费
- 个位数毫秒延迟:无论表的大小如何
- 高可用:数据自动复制到三个可用区
表设计
操作日志的数据模型:
表名: user_actions
Partition Key: user_id (String) — 按用户分区
Sort Key: sk (String) — timestamp#action_id,按时间排序
设计考虑
- Partition Key 选择高基数字段(user_id),避免热分区
- Sort Key 使用时间戳前缀,支持按时间范围查询
- 追加 uuid 后缀防止同一毫秒的写入冲突
代码实现
写入
import boto3, time, uuid
table = boto3.resource('dynamodb', region_name='ap-northeast-1').Table('user_actions')
table.put_item(Item={
'user_id': 'u_12345',
'sk': f'{int(time.time())}#{uuid.uuid4().hex[:8]}',
'action': 'click_button',
'page': '/dashboard',
'details': {'button_id': 'submit', 'form': 'login'}
})
查询
from boto3.dynamodb.conditions import Key
response = table.query(
KeyConditionExpression=Key('user_id').eq('u_12345'),
ScanIndexDirection=False,
Limit=20
)
批量写入
with table.batch_writer() as batch:
for event in events:
batch.put_item(Item={
'user_id': event['user_id'],
'sk': f'{event["ts"]}#{uuid.uuid4().hex[:8]}',
'action': event['action'],
'page': event['page']
})
batch_writer 自动分批(每批 25 条),自动处理限流重试。
迁移过程中的问题
热分区
部分系统账号(如 admin、system)的写入量远超普通用户,导致对应分区被限流。
解决方案:对高频 Partition Key 添加随机后缀进行分片。
Scan 陷阱
初期有个报表查询用了 table.scan(),扫描 200GB 数据耗时 3 分钟。改成 GSI + Query 后降到毫秒级。
生产环境应避免使用 Scan,所有查询走 Query 或 GSI。
GSI 一致性
Global Secondary Index 是异步复制的,存在毫秒级延迟。写入后立刻通过 GSI 查询可能读不到最新数据。需要强一致性的场景使用主表 Query。
迁移前后对比
| 指标 | MySQL (RDS r5.large) | DynamoDB (On-Demand) |
|---|---|---|
| 月成本 | ~$190 | ~$25 |
| 写入延迟 (P99) | 15ms | 5ms |
| 扩容方式 | 手动/预定义 | 全自动 |
| 运维工作量 | 备份/监控/升级 | 接近零 |
| 查询灵活性 | SQL 支持所有查询 | 只支持主键/索引查询 |
适用性分析
DynamoDB 适合:
- 写入密集 + 读取模式固定 的场景
- 需要自动弹性扩缩的应用
- Key-Value 或宽列数据模型
关系数据库更适合:
- 查询模式复杂多变(JOIN、聚合、子查询)
- 强数据关联(多对多关系)
- 需要事务一致性保障的金融场景
小结
这次迁移的核心收益是成本降低 87% 和运维工作量接近归零。DynamoDB 的按需计费模式在写入量波动大的场景下有明显的成本优势。
局限性方面,查询灵活性不如 SQL,表设计需要提前考虑好访问模式。但对于明确的 Key-Value 查询场景,DynamoDB 的性能和成本表现确实很好。
以上代码基于亚马逊云科技 DynamoDB + Python boto3 验证通过。

浙公网安备 33010602011771号