数据库中的万圣节问题(Database "Halloween problem")

参考文献:

1.What is the Halloween Problem in databases?

2.Halloween Problem

3.Table scans to avoid the Halloween problem

4.数据库索引实例

正文

  今天在看《数据库系统概念》这本书的查询优化章节,在其中的第13.6.3节中提到了万圣节问题(Halloween problem)。这是一个挺有意思的问题,不过现在已经不存在这样的问题了,大多数数据库管理系统都为我们解决了这样的问题。不过我们可以来看看这个万圣节问题到底是什么。

  在1976年的万圣节那一天,IBM的两位程序要需要修改数据库库中内容,其所对应的业务内容是“给所有工资小于25000的员工加薪百分之十”,他们运行的sql语句如下:

UPDATE EMP_TABLE SET SALARY=SALARY*1.1 WHERE SALARY<25000

  但是他们执行完这条语句以后发现了一个大问题,那就是数据库中所有员工的工资都至少为25000。后来发现出现这样的结果的主要问题是:所有工资小于25000的哪些记录被无限次数得加薪了百分之十,直到工资大于等于25000为止

   如果更新操作是在选择操作扫描索引的执行过程中完成,一个更新的元组可能会在扫描之前和扫描之后重复插入索引两次;同一个元素的元素可能不正确地更新多次(在上述情况下会更新多次直到工资大于等于25000为止)。上述更新操作本身可能影响自己执行的问题称为万圣节问题(Halloween problem)。在前面的博客:数据库索引实例中我们提到,如果我们在一个字段上创建了索引,那么元组会按照索引进行排序。假如我们在之前的EMP_TABLE表中的SALARY字段上创建了所以呢,那么每次更新SALARY字段都会更新索引,然后对元组的位置进行调整。假设原本数据库中有三个员工信息,内容如下:

1 张三 2000
2 李四 2100
3 王五 2300

然后执行工资增加10%的操作,在更新第一条记录(1 张三 2000)以后,这三条记录在数据库中的存储位置如下:

2 李四 2100
1 张三 2200
3 王五 2300

然后继续更新第二条记录(2 李四 2100),更新以后三条数据库记录的位置如下所示:

1 张三 2200
3 王五 2300
2 李四 2310

这一次我们需要再一次更新(1 张三 2200)这条记录,那么这一条记录就更新了多次。这也是造成万圣节问题的根本原因所在。

  如果更新不影响索引属性,则万圣节问题不会发生。即使影响索引属性,如果更新减小该值,而索引扫描以升序执行,更新过的元素在扫描时不会再遇到。在这种情况下,查询执行的同时可以更新索引。

  不过现在的数据库管理系统基本解决了万圣节问题,不会再出现上述情况,不过具体的解决方法是什么,我还有待研究。

举例

我们以数据库索引实例的示例来进行说明,假设一张表emp_pay(employeeID, base_pay, commission),其中在base_pay上加了索引,因此最后查询结果以base_pay的升序显示,查询结果如下;

然后我们执行一个加薪的sql,让所有工资大于100的员工加薪10%,那么假设存在万圣节问题,那么employeeID为7的员工可能会出现多次加薪,但是当我们执行下述sql以后,发现并没有出现万圣节问题:

UPDATE emp_pay SET base_pay=base_pay*1.1 WHERE base_pay>100

进行加薪以后我们再次执行查询语句,查询结果如下:

从上述查询结果我们可以发现,每个员工都只加工了一次。这也说明在现在的关系数据库中,数据库管理系统已经帮我们解决了万圣节问题。

原文地址:https://www.cnblogs.com/xwdreamer/p/2522404.html