之前有介绍过,我主要是做数据仓库运维的,业余也会动手写 python 程序,django 应用,vue 的 app,有兴趣可以加我好友一起学习。最近比较让我头疼的是数据仓库的 datastage 作业经常报 911 错误,最终问题得到了解决,在此总结一下,希望能帮到要解决 911 错误的朋友们。
先介绍下数据仓库的概念:
一个面向主题的、集成的、非易失性的、随时间变化的数据的集合,以用于支持管理决策过程,是一个典型的 OLAP(Online analytical processing)系统。
数据仓库的架构如下图所示:
上图中从数据的抽取、加工转换、到数据集市、到最后的数据分析、报表,有数以万计的加工程序,数据库连接的进程也是成百上千,这也是最容易出现 911 报错的场景。
1、什么是 911 ?
911 是 db2 数据库的一种错误码,表示锁超时或死锁。锁超时就是一个事务 A 需要的资源正在被别的事务 B 占有,假如数据库设置的超时时间为 60 秒,超过了 60 秒,事务 B 仍没有释放资源,那么事务 A 将报锁超时错误并回滚。而死锁就是事务 A 需要的资源正在被事务 B 占有,事务A 等待,事务 B 需要的资源正在被事务 A 占有,事务 B 也等待,那么就发生了死锁,此时数据库会选一个成本较小的事务进行回滚。
2、什么情况会发生 911
我们已经知道 911 是关于锁的一种错误,要么是锁超时,要么是死锁。那么就需要对锁有一个细致地了解,上一篇文章介绍过【运维必备之db2 的锁】,默认情况下,db2 的 select 语句的隔离级别是【游标稳定性(Cursor Stability)】,即 select * from table with cs , 这种隔离级别会在查询的行上加上 NS 锁,NS 锁的中文名称叫【下一键共享锁(Next Share)】,拥有者与其他程序都可以读取该行,但不能进行修改。比如当一个进程(事务) A 正在查询该行时,进程(事务) B 试图更新(update)该行,那么进程(事务) B 就会等待,如果超过 60 秒(假如数据库设置超时为 60 秒),进程(事务) A 仍在查询中,没有释放,那么进程(事务) B 就会回滚,并报 911 错误,有些进程还会提示原因码为 68。
而有些工具为了支持并发,如 datastage ,会将一个批量更新或插入的语句拆分成多个进程同时执行,从而提高效率。如果多个进程同时 update 相同的多行数据。 比如:一个进程(事务) A 已经修改行 1,但未提交,准备修改行 2 后一起提交,但行 2 上有排他锁 X , 进程(事务) B 已经修改行 2,但未提交,准备修改行 1 后一起提交,但行 1 上有排他锁 X,此时 A 与 B 互相等待,进入死