SQL语言艺术(九)多条战线:处理并发

这章讨论如何应对大量并发用户的情况

一个测试时很高效的查询可能在大并发情况下执行地很慢,而且当大量语句并发执行,如果SQL语句提交的速度比服务速度要快时,系统性能就会出现严重问题,所有查询都会受到影响,原先较快的查询也会变慢

负载增加未必是造成性能问题的原因,它只不过使性能问题暴露出来了而已。此时,建议改善程序,而不是升级硬件

修改操作本质上比查询代价更高,不仅牵涉取得数据,还涉及写回数据,往往比查询要花更长时间。另外加锁机制和资源争用会引起上述情况恶化

加锁

解决并发修改的冲突涉及到锁的使用,锁会影响以下内容:

整个数据库
存储被修改的表的那部分物理单元
要修改的表
包含目标数据的块或页
包含受影响数据的记录
记录中的字段

加锁的数据量小(细粒度锁),则多个并发进程就可能同时修改同一表中的数据,而不会造成阻塞,从而提高硬件资源的利用率

如果由于加锁的影响,DBMS变得非常缓慢,那么对付突然增加的负载量唯一办法就是购买更好的硬件了。更好的硬件能否提升性能也是有条件的,如果是锁造成的性能瓶颈,更多的处理器也于事无补,因为关键资源是数据存取。当然,较快的处理器可以加速执行,降低实际加锁时间,因此单位时间的吞吐量将会增加

在处理加锁的时候要注意不要随便使用表级锁,尽量缩短加锁时间。大多数的update和delete语句都包含where子句,通过改写where子句能加快select的执行,也能加快update和delete的执行。如果delete语句没有where子句,使用truncate清空表更高效。另外索引也需要维护,更新加了索引的字段代价很高,所以我们必须在读取速度和更新速度之间进行权衡

事务

在程序中还应该考虑事务。大多数事务要求保留数据库特定部分的锁,所以不需要在事务中完成的工作,尤其是耗时的工作,应该排除在事务之外。在事务内,应该注意:
尽可能避免SQL语句上的循环处理
尽量减少程序和数据库的交互次数
充分利用DBMS提供的机制(例如存储过程),使跨机器交互的次数降至最少
把所有不重要,不必须的SQL放到事务之外

加锁与提交

想要使加锁时间最短,就必须时行频繁的提交。提交是代价极高的处理,因为它意味着对日志文件的写操作,涉及物理I/O操作。延迟提交会延长加锁时间,且系统要为undo操作记录更多改变前的数据映像,如果操作失败,事务回滚也要花更长的时间。并发用户数越多,提交的间隔就应该越短

资源竞争

与加锁不同,数据库竞争可以改善。DBA,架构师,开发者都可以从各自的角度改善竞争

你可能感兴趣的:(sql,工作,单元测试)