若两个事务不触及相同数据,即无数据依赖关系,则它们能安全并行运行。只有当:
才会出现并发问题。
并发 BUG 很难通过测试找到,因为这样的错误只有在特殊时序下才会触发。这样的时序问题可能非常少发生,通常很难重现 1。并发性也很难推理,特别是在大型应用中,你不一定知道哪些其他代码正在访问DB。只有一个用户访问数据时,应用开发就够麻烦了,多用户并发更困难,每个数据都可能被多个用户修改。
因此,DB一直试图通过【事务隔离】来隐藏内部的各种并发问题。理论上,隔离是假装没有并发发生,让程序员生活不再加班。而可串行化隔离级别就是DB保证事务最终效果如同串行执行。但可串行化会有极大性能损失,许多DB不愿意牺牲性能,所以倾向较弱隔离级别,防止某些而非全部并发问题。
弱隔离导致的并发性错误不仅是理论问题,它们已造成很多资损,审计调查和客户数据破坏。比起盲目依赖工具,不如对各种并发问题及如何防止有深入理解,构建可靠、正确的应用。
最基本的事务隔离级别2,提供如下保证:
某事务已完成部分数据写,但事务尚未提交或中止。另一个事务可以看到尚未提交的数据吗?是,则为脏读。
防止脏读的意义
若两个事务同时尝试更新DB的相同对象,不知道写的顺序如何,但通常认为后写入会覆盖前写入。
互联网主流隔离级别,Oracle 11g、PostgreSQL、SQL Server 2012、MemSQL和其他许多DB的默认设置。
DB一般通过 行锁(row-level lock)防脏写:当事务想修改某对象(如行或文档),必须首先获得该对象的锁。然后一直持有直到事务提交(或中止)。一次只有一个事务可持有特定对象的锁;若另一事务要更新同一对象,则必须等到前面事务提交或中止后,才能获取锁并继续。这是RC模式(或更高隔离级别)的DB自动完成的锁定。
因此,大多DB 3 使用图-4方案防脏读:对于写入的每个对象,数据库都会记住旧的已提交值,和由当前持有写入锁的事务设置的新值。当事务正在进行时,任何其他读取对象的事务都会拿到旧值。 只有当新值提交后,事务才会切换到读取新值。
阅读量:2015
点赞量:0
收藏量:0