在生产库上执行 SQL 要谨慎

156 阅读2分钟

本文正在参加「技术专题19期 漫谈数据库技术」活动

你是否有过这样的经历:本地执行没什么问题,在生产环境的数据库执行时就出现问题了;看似没什么问题的 SQL 语句删除冗余数据,但是在生产上执行后就发生了问题。

当你负责很多项目,可能涉及多组件,数百万行的代码,数千个配置以及具有数百个表的复杂系统时,你所做的任何事情都必须非常小心。生产的数据经常都是无法拿来测试的。所以最好的办法是多检查验证,或者让所有的更改尽可能的独立和有限。

为了安全起见,在生产环境中运行 SQL 语句时需要注意五个事项:

始终使用 NOLOCK 进行查询

NOLOCK 可以降低阻塞和死锁的风险。当你在查询时刚好某个任务也正在运行且将会更新你正在查询的一个表,可能就会导致产生问题。如堵塞了生产环境要更新的工作。使用 NoLock 查询其实就是告诉 SQL 查询时不加锁,相当于读未提交。

查询时增加 WITH(NOLOCK) 选项就可以让查询不加锁,这一用法是只有 MS SQL 中使用。如果在 MySQL 中设置查询不加锁,需要通过 Set 语句:

# ms sql
select username , age from userinfo ;

# mysql 
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

当然使用 NOLOCK 的方式,发生脏读是可能的。所以使用的也要注意,允许使用但不允许滥用。以下场景情况下是可以考虑使用:

  • 数据变更少的表,比如基础表,设置表、历史数据表
  • 允许脏读情况的业务表
  • 数据量大的表,但因性能考虑允许脏读

在生产环境上运行之前一定要在测试环境上执行

像一些数据变更的语句,应当尽量在测试环境上提前演练执行没有问题之后再用在生产环境上执行。这样不仅可以提前验证自己的预期内容,还可以避免在生产中出现错误语法错误和意外错误的问题。

在备份库或只读库中执行你的查询

如果可以的话,尽量在备份库或者只读库的上执行查询,而不是在主服务器上运行。当你觉得数据不是最新的时候且无法使用备份库时,可以考虑使用主数据库,但尽量避免在生产时间使用。

生产高峰期或活跃期避免使用生产数据库

像比如电商的抢购高峰期,证券交易所的交易时间,应当尽量避免在此期间接触生产数据库。