前言:本章讨论多个SQL语句同时执行的必要性和所需的基础设施。
锁
锁是数据库服务器用来控制数据被并行使用的一种机制。当数据库的一些内容被锁定时,任何打算修改(或者可能是读取)这个数据的用户必须等到锁释放。大部分数据库使用以下两种锁策略之一。
策略一:数据库的写操作必须向服务器申请并获得写锁才能修改数据,而读操作必须申请和获得读锁才能查询数据。多用户可以同时读取数据,而一个表(或其他部分)一次只能分配一个写锁,并且拒绝读请求直至写锁释放。
策略二:数据库的写操作必须向服务器申请并获得写锁才能修改数据,而读操作不需要任何类型的锁就可以了查询数据。另一方面,服务器需要保证从查询开始到结束读操作看到一个一致的数据视图(即时其他用户修改,数据看上去也要相同)。这个方法被称为版本控制。
这两种方法各有利弊,第一种方法在有较多的并行读取请求和写请求时等待时间过长;如果在修改数据时存在长期运行的查询,则第二种方法也是有问题的。
在常用的数据库服务器中,Microsoft SQL Server采取第一种方法,Oracle采取第二种方法,MySQL则两种方法都包括(取决于使用者对存储引擎的选择)。
锁的粒度
决定如何锁定一个资源时也可以采用一些不同的策略。服务器可能在3个不同级别之一应用锁,或者称为粒度:
表锁:阻止多用户同时修改同一个表的数据。
页锁:阻止多用户同时修改某表中同一页(一页通常是一段2~16KB的内存空间)的数据。
行锁:阻止多用户同时修改某表中同一行的数据。
同样,这些方法各有利弊,表锁需要较少的簿记就可以锁定整个表,但是当用户增多时它会迅速产生不可接受的等待时间。另一方面,行锁需要更多的簿记,但是只要各个用户的兴趣在不同的行,它就能允许多人修改同一个表。
在常用的数据库服务器中,Microsoft SQL Server使用表锁、页锁和行锁,Oracle只有行锁,MySQL使用表锁、页锁和行锁(同样取决于使用者对存储引擎的选择)。在某些情况下,SQL Server会将锁从行锁升级至页锁,再从页锁升级至表锁。然而Oracle数据库从不升级锁。