经过一段时间的学习和使用,我对DB2有了一定的了解,现在将一些心得记录下来,方便以后
db2 锁定会在需要一个事务时被自动获取,在事务终止时被释放(使用一条COMMIT或ROLLBACK命令)。锁定有两种:
S锁定(共享锁定) —— 当程序企图读并且禁止其他程序修改同一行时被获取的锁定;X锁定(互斥锁定) —— 当一个程序修改,插入或者删除一行时被获取;
并发控制需解决的四种问题
丢失更新(Lost update)
描述:
App1 修改一行;
App2 修改同一行;
App1 提交;
App2 提交;
结果:
App2进行更新时,App1的更新就丢失了。
未落实的读(Uncommitted read)
描述:
App1修改一行;
App2读取该行的新值
App1回滚它对该行的更改
结果:
App2读取的是未提交的数据,所以该数据是无效的;
不可重复读(Non-repeatable read)
描述:
App1打开一个游标(亦即结果集)获取结果;
App2删除游标限定的一行;
App2提交更改;
App1关闭并更新开启游标;
结果:
在此情况下,因为App1在一次重复的读中不会得到同一份的数据,所以它不能够重新产生这个数据集;
幻象(Phantom read)
描述:
App1开启一个游标
App2向数据库中添加了一个行,该行与游标匹配;
App2提交更改;
App1关闭并且重新开启游标
结果:
在此情况下,App1在重复的读取中获取的将不是同一个数据,它将得到更多的行;
针对于以上四种问题,db2提供了不同的保护级别:
未落实的读(UR)
未落实的读亦称“脏读”。它是最低的隔离级别,并且提供最高的并行性。除非另一个程序企
图删除(drop)或者更改(alter)整个表,否则读操作时没有行锁定;而修改(update)操作与游标稳定
性级别相同。
此隔离级别仍存在的问题:
* 未落实的读
* 不可重复读
* 幻象
此隔离级别所防止的问题:
* 丢失更新
游标稳定性(CS)
游标稳定是默认的隔离级别。它提了低程度的锁定。在这一隔离级别中,游标的“当前”行是
锁定的。如果该行只是被读的,锁定会一直持续到一个新行被访问或者该工作单元终止。如果该行被
修改,锁定会一直持续到该工作单元终止。
此隔离级别仍存在的的问题:
* 不可重复读
* 幻象
此隔离级别所解决的问题:
* 丢失更新
* 未落实的读
读稳定性(RS)
使用读稳定性,在同一个工作单元中的一个程序进程所检索的全部行都会被锁定。对于一个给
定的游标,它要锁定所有与结果集匹配的行。例如,如果您有一个含 1000行的表并且查询返回 10
行,那么只有那 10行会被锁定。读稳定性使用中等级别的锁定。
此隔离级别仍存在的问题:
* 幻象
引隔离级别所解决的问题:
* 丢失更新
* 未落实的读
* 不可重复的读
可重复读(RR)
可重复读是最高的隔离级别。它提供了最大程度的锁定和最少的并行。产生结果集的所有行都
会被锁定,也就是说,即使不必出现在最终结果集中的行也会被锁定。在此该工作单元结束前,任何
其它的程序都不能修改,删除或插入一个会影响结果集的行。重复读确保程序在一个工作单元中多次
进行的同一项查询都返回结果。
此隔离级别仍未解决的问题:
* 无
此隔离级别解决了的问题
* 丢失更新
* 未落实的读
* 不可重复的读
* 幻象
最佳实践
遵循以下建议有助于最佳地实现可能的并行
1、使事务尽可能地短小。这可以通过在您的程序逻辑允许的情况下频繁地使用COMMIT语句
(即使对只读的事务也一样)来实现。
2、只有必要时才记录事务信息。
3、快速清理数据:
ALTER TABLE ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE
4、成批或成组地修改数据,例如:
DELETE FROM ( SELECT * FROM tedwas.t1 WHERE c1 = … FETCH FIRST 3000 ROWS ONLY)
5、利用 DB2的数据转移工具中的并行特性。
6、设置数据库级的LOCKTIMEOUT参数(推荐值为30~120秒之间)。不要保留为默认值-1。您也可以使用基于会话的超时锁定。
7、不要检索不需要的数据。例如,在SELECT语句中使用FETCH FIRST n ROWS ONLY 子句。
对比一下,以前用的oracle,它支持两种事务类型读写事务、只读事务。并发控制分为写丢失、读写冲突,其中,写丢失和db2中第一种情况类型,db2中第二、三、四种情况全部归在读写冲突中。