从Ruby代码层面排查和优化
- 排查步骤
- 检查事务逻辑:查看代码中事务的使用,是否存在多个事务相互等待资源的情况。例如,是否有两个事务,一个先获取资源A再获取资源B,另一个先获取资源B再获取资源A。
- 分析查询语句:检查频繁执行的SQL查询,是否存在效率低下的情况,比如全表扫描、未使用索引等。
- 优化策略
- 优化事务处理:
- 减少事务粒度:尽量缩短事务的执行时间,只在必要时开启事务,将无关操作移出事务。
- 按相同顺序访问资源:如果多个事务需要访问多个资源,确保按照相同的顺序获取资源,避免死锁。
- 优化SQL查询:
- 添加索引:根据查询条件,在数据库表的相应字段上添加索引,提高查询效率。
- 使用预编译语句:在Ruby中使用ActiveRecord等ORM框架时,使用预编译语句(如
find_by_sql
方法传递预编译的SQL),减少SQL解析开销。
- Ruby代码片段
ActiveRecord::Base.transaction do
# 尽量减少这里面的代码量,只放必要的数据库操作
user = User.find(1)
user.update_attribute(:name, 'new_name')
end
sql = "SELECT * FROM users WHERE age >? AND status =?"
users = User.find_by_sql([sql, 18, 'active'])
从PostgreSQL数据库层面排查和优化
- 排查步骤
- 查看死锁日志:PostgreSQL的日志文件(通常在
postgresql.conf
配置文件中指定的日志目录下)会记录死锁相关信息。通过查看日志,可以了解死锁发生时涉及的事务和SQL语句。
- 监控数据库负载:使用
pg_stat_activity
视图查看当前数据库的活动连接和执行的SQL语句,分析哪些查询占用资源较多。
- 检查索引使用情况:通过
EXPLAIN
命令查看查询计划,了解是否正确使用了索引。
- 优化策略
- 处理死锁:
- 设置合理的死锁超时:在
postgresql.conf
中设置deadlock_timeout
参数,适当缩短死锁检测时间,让系统更快地发现并解决死锁。
- 调整事务隔离级别:根据业务需求,选择合适的事务隔离级别,例如从
SERIALIZABLE
调整为READ COMMITTED
,降低死锁发生的概率,但可能会引入其他并发问题,需谨慎评估。
- 应对高负载:
- 优化索引:根据查询需求创建、删除或重建索引,确保索引的有效性。
- 配置参数优化:调整
shared_buffers
、work_mem
等参数,优化数据库内存使用,提高查询性能。
- 负载均衡:使用PgBouncer等工具进行连接池管理和负载均衡,减轻单个数据库实例的压力。
- PostgreSQL命令
- 查看死锁日志:查看
postgresql.log
文件,搜索关键字“deadlock detected”。
- 监控数据库负载:
SELECT * FROM pg_stat_activity;
EXPLAIN SELECT * FROM users WHERE age > 18;
- 设置死锁超时:修改
postgresql.conf
文件,添加或修改deadlock_timeout = 1s
(这里设置为1秒,可根据实际情况调整),然后重启PostgreSQL服务。
- 调整事务隔离级别:
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED;