陈辉
作者陈辉·2013-03-14 21:30
研发工程师·IBM

【DPS】关于DB2 log buffer中日志何时写入磁盘的问题

字数 1761阅读 4375评论 1赞 1
帮一位同学解决的问题,发布出来,一方面便于自己总结,另一方面希望可以帮助大家。

Qusestion1:请教个问题!如果我更新一条记录,未做commit或rollback,那么此时日志是否只存在log buffer中而不会写到磁盘上? 如果是,若此时有大量的读操作将刚才更新的记录从缓冲池写到磁盘后,突然crash,那么崩溃恢复的时候这条更新的记录如何处理的(log buffer的记录没了)?
不知道我的这种情况是否存在,期待您的回复,谢谢!

Answer1:你好,
先 回答你第一个问题,日志从log buffer写入到磁盘,有三种情况:1.commit。 2.log buffer满 3.Page steal 4.softmax 5.Some database operations(DDL at storage level call) 6.The most common time to write is when loggw wakes up and there is a full page。所以,有可能你还没有commit,但是log record也会写入磁盘。但是你一旦commit,则数据库肯定会将log 写入磁盘。

第二个问题,你是不是问,在没有commit之前,数据有没有可能从buffer pool写入到磁盘?答案是肯定的,有可能。但是数据库内部会有一些机制来解决这个问题,以保证数据的准确和安全,例如lowtran和 minBufLsn,在crash之后,会进行redo和undo的操作,把commit的日志redo,把没有commit的日志undo,相应的数据 也会清理掉。不会存在脏数据的风险。

那么崩溃恢复的时候这条更新的记录如何处理的(log buffer的记录没了)?
针对你的问题,因为还没有commit,所以答案就是数据库会用undo操作,把这些数据清理掉,undo用的是log file(磁盘上),不会用log buffer。

我理解你可能想说的是脏读的问题,这边的app还没有commit,另外一个app已经读到数据并写入磁盘,一般情况下,脏读是不允许的。如果用户自己选择脏读,后果用户自己处理,数据库不可能保证脏读数据的安全,否则就不叫脏读了。所以,请慎重选择隔离级别。

Question2:针对下面这段:
数 据库内部会有一些机制来解决这个问题,以保证数据的准确和安全,例如lowtran和minBufLsn,在crash之后,会进行redo和undo的 操作,把commit的日志redo,把没有commit的日志undo,相应的数据也会清理掉。不会存在脏数据的风险。
我从资料中看到,做redo和undo都是根据写入到log里面的记录进行的,那如果log在内存里还没有及时写入磁盘,crash后日志没了,怎么做redo和undo? 我举个例子:
1.tran1对一条记录做update并且未提交,这时1.commit。 2.log buffer满 3.softmax这3中情况都不存在,也就是说log还在buffer里面;
2.tran2读取很多记录,把刚才那条update的记录从缓冲池刷到磁盘去了,此时这条记录是脏数据,对吧?
3.crash,刚才那条update的log丢失,磁盘也没有
4.crash recovery,如何回滚这条update的记录?
就是这么个情况,想知道这种情况DB2内部是如何处理的,谢谢!

Answer2:我明白你的意思了,你说的叫Page steal, Buffer pool在page不够的情况下,会将一些脏页(可能是没有commit的事务的页)写回磁盘,发生这种情况时,首先会将log buffer flush,也就是将日志写入磁盘,然后才会处理data,之后还会更新minBuffLsn的值,该值指示当前最早的脏页对应的log record的LSN。而min(lowtranLSN, minBuffLsn)是crash recovery的起点。

总而言之,你要记住一点,事务管理中任何写数据操作之前一定会先写日志。这是任何数据库支持事务的前提,只有这样才能保证数据的安全。









如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

1

添加新评论1 条评论

atpeace331atpeace331数据库管理员银行
2013-10-11 14:44
老师,回答的很精辟。
Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广