ORACLE DBA非常有必要简单的了解下。写这个文档,我得出的结论是,我们小事务居多的网站,以后升级到10GR2后,可以考虑改变日志提交方式为batch , wait。这种方式不丢数据,节省了日志浪费,省了更多的redo blocks。
禁用了imu,batch也就没了作用。commit都会变成stand alone的commit record。
10GR2后,ORACLE提供了一个新参数commit_write来控制客户端commit后,ORACLE写日志的行为。这个参数值有四种组合。
· immediate , wait
· immediate , nowait
· batch , wait
· batch , nowait
传统的,我们的默认写方式都是immediate , wait。代表服务进程立即通知LGWR刷新日志,LGWR刷新完log buffer后通知SERVER进程,COMMIT成功。
11G后,ORACLE进一步的把这个参数拆成了两个参数来控制。
commit_logging和commit_wait.
commit_logging的值可以设置为batch/immediate。
commit_wait的值可以设置为wait/nowait。
以下是童家旺对这几个值组合后的解释,不敢保证绝对正确,某些点(immediate,nowait )我不认同,但是基本说服了我。
- immediate,wait
Server Process在提交时使用semctl发送信号给LGWR,通知其Flush Log Buffer,并等待LGWR发回的消息(semtimedop).
LGWR在接收到消息后, Flush log buffer到磁盘,通过semctl 发送信号给Server Process,告知其commit成功.
- immediate,nowait
Server Process在提交时使用semctl发送信号给LGWR,通知其Flush Log Buffer,不等待LGWR发回的消息.
LGWR在接收到消息后, Flush log buffer到磁盘(到此结束)
- batch,wait
Server Process在提交时使用semctl发送信号给LGWR,要求其提交后通知此Server Process进程, 并等待此消息返回(运行semtmdop)
LGWR在经过一定的内部时间(Timeout)后, Flush Log Buffer到磁盘,并使用semctl通知此Server Process进程
- batch,nowait
Server Process将日志信息写入Log Buffer之后,就不再关心此问题
LGWR进程按照自己的规则(可能是一次Timeout),将日志写入在线日志文件, 不会通知此Server Process进程.
也就是在这种情况下, Server Process与LGWR进程基本都不会使用semctl/semtimedop做任何通知. 此时LGWR的只是单纯的服务LOG的写操作, 而不再需要其他的处理(LGWR Processing 过程)
lewis在他的新书里提到如果用了nowait选项,your session doesn’t send a message to lgwr at all;童家旺immediate,nowait 的猜测里,是通知lgwr了。我个人对大师是极其的崇拜,更倾向大师的结论(别骂我没自己的思想),而且他的测试结果immediate nowait的redo synch writes 日志同步写次数为0,是不是能证明没通知LGWR?
以下是 lewis的测试结果。他的测试是在没并发的情况下测试的。测试脚本一共循环了25次。每次循环后提交。小事务。
The bottom line with the new commit options is simple: if you really need to ensure that every
commit is guaranteed to be recoverable (e.g., in a banking system or medical system), then you should
use the wait option, and the batch wait combination ought to give you a little edge of efficiency if the
transactions are all small. If you don’t mind risking a few committed transactions disappearing in the
event of an instance crash (e.g., a social network), then batch nowait is clearly worth looking at for the
reduction in redo, redo wastage, and session waits.
lewis建议我们,如果你的系统的数据非常的重要,不能丢失任何的数据,那么需要确认wait选项,如果你的事务都是非常的小,那么batch wait将会稍微提高你的事务效率,减少了redo blocks的浪费,后面还会有个简单的对比。如果你的系统的数据丢失一点没关系,那么batch nowait是你最好的选择。这种组合对于redo的size,redo的浪费,以及用户的等待时间都是最小的。
If you specify immediate rather than batch, then two key changes appear: the commit change vector
becomes a separate redo record (I can’t think why; perhaps it’s to minimize the time window on the
ACID anomaly I previously mentioned), which gives you a small increase in the redo size, and—
provided you haven’t specified wait—your session doesn’t send a message to lgwr at all; it simply
assumes that something else will trigger a write in the near future.
batch和immediate有个关键的不同,immedaite把commit当成是一个单独的改变向量。lewis的测试结果里immediate比batch多了一倍的redo entries。这一倍的实际内容就是commit本身产生的。这里有一点疑惑就是,lewis的意思,好像不管是batch,还是immediate,在指定nowait时候,事务都是在in the near future进行提交,而不是立即提交。我以前的理解是batch是in the near future提交的,immediate是立即提交的,只是不等待lgwr写完成而已,还是那句话,对大师太崇拜,还是相信大师,从他的测试结果里,也能得出这样的结论,Immediate nowait和Batch nowait的redo synch writes次数都是0,即没有立即进行日志写。
阿里巴巴绝大多数的数据库目前都是immediate wait的方式,个人建议,网站类的应用可以设置为batch wait的方式(可惜目前阿里巴巴网站大多是9I),原因是这类的应用一般都是小事务居多。重新把lewis的测试结果,只摘录immediate wait和batch wati来做比较。
Statistics name |
Immediate wait |
Batch wait |
messages sent |
25 |
25 |
redo entries |
50 |
25 |
redo size |
12752 |
12068 |
redo synch writes |
25 |
25 |
redo wastage (lgwr) |
12048 |
3804 |
redo blocks written (lgwr) |
50 |
32 |