最近在做数据迁移,发现用数据库泵要比用DML语言(insert)快很多,大概一个8G左右的表数据库几分钟就可以导入成功,而用DML语言需要2-3个小时才能完成。最初以为机器性能不行,想起来最进接触的Linux HugePages相关知识。
通过后来学习发现在数据库内存为AMM管理模式下,不支持Linux HugePages。
关于相关说明:HugePages and Oracle Database 11g Automatic Memory Management (AMM) on Linux (文档 ID 749851.1)
Linux HugePages说明:http://blog.csdn.net/zhouyh139/article/details/8662768#comments
查看v$log表,发现绝大多数日志为active状态。遂将DML语言改为并行nologging形式:
insert /*+position(t1,4)*/ into t1 select /*+position(t2,4)*/ * from t2 nolongging;
发现还是不行,依旧很慢。无奈给数据库做了一个statspack。发现问题:
Top 5 Timed Events Avg %Total
~~~~~~~~~~~~~~~~~~ wait Call
Event Waits Time (s) (ms) Time
----------------------------------------- ------------ ----------- ------ ------
db file async I/O submit 208 1,740 8367 42.6
free buffer waits 804 1,552 1930 38.0
rdbms ipc reply 150 282 1880 6.9
log file parallel write 1,776 219 124 5.4
db file scattered read 3,299 107 33 2.6
-------------------------------------------------------------
发现db file async I/O submit等待事件,且每个等待高达8367秒。同时还伴有free buffer waits等待事件,先查询后者如下:
这个等待事件出现是因为dbwr没有及时将dirty buffer写到磁盘,造成server process得到不到free buffer。造成dbwr写脏块慢的原因主要由以下几种情况:
检查v$filestat,是否大量磁盘写操作发生;通过iostat等操作系统命令查看磁盘写情况。
可以通过换更快速磁盘及I/O分担的方法解决i/o慢的问题。
通过V$DB_CACHE_ADVICE获得较合理的buffer cache大小并进行调整。
增加dbwr进程。如果多个cpu,建议通过修改db_writer_processes增加dbwr进程;如果是单个cpu,建议通过修改dbwr_io_slaves增加dbwr slave进程。来提高dbwr刷新速度。
通过分析锁定问题是第一种I/O慢, 通过查看IO状态确定如此:
[root@localhost oracle]# iostat -k -x 1 10
avg-cpu: %user %nice %system %iowait %steal %idle
5.88 0.00 0.75 7.88 0.00 85.50
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 48.00 5315.00 155.00 104.00 18520.00 20668.00 302.61 3.13 12.03 3.67 95.00
sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda5 48.00 5315.00 155.00 104.00 18520.00 20668.00 302.61 3.13 12.03 3.66 94.90
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.00 163.00 0.00 163.00 0.00 1304.00 16.00 1.00 6.13 6.12 99.70
sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda5 0.00 163.00 0.00 163.00 0.00 1304.00 16.00 1.00 6.13 6.12 99.70
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
发现/dev/sda5即/U01这块盘的IO一直是接近100%,但是我做了一个系统测试发现写的能力又不是那么弱.
[oracle@localhost ~]$ time dd if=/dev/zero of=/u01/testio.dmp bs=8k count=300000
300000+0 records in
300000+0 records out
2457600000 bytes (2.5 GB) copied, 7.13211 seconds, 345 MB/s
real 0m7.193s
user 0m0.124s
sys 0m4.328s
于是放狗去找,在metalink上找到一篇关于该问题的描述:
'db file async I/O submit' when FILESYSTEMIO_OPTIONS=NONE (文档 ID 1274737.1)。但该文章说在11.2.0.3中已经解决这个问题了。
但在11.2.0.3中已经将该BUG解决,我的版本为11.2.0.3.7的,不存在该问题。通过学习查找汇总:
在11G中,默认异步IO是打开的:
SQL> show parameterdisk_asynch_io
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
disk_asynch_io boolean TRUE
但是实际filesystemio_options并没有设置
SQL> show parameter filesystem
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
filesystemio_options string none
filesystemio_options有4中状态:
· ASYNCH - Enabled asynchronous I/O where possible.
· DIRECTIO- Enabled direct I/O where possible.
· SETALL- Enabled both direct I/O and asynchronous I/O where possible.
· NONE - Disabled both direct I/O and asynchronous I/O.
也就是说目前数据库默认filesystemio_options不是支持同步或异步I/O的,所以我想用异步IO就需要将数据库开启支持的状态。
在Oracle11gR2中AIO默认已经是开启的了。可以通过ldd或者nm来检查oracle是否已经启用了AIO支持,有输出代表已经启用。
[oracle@localhost ~]$ /usr/bin/ldd $ORACLE_HOME/bin/oracle | grep libaio
libaio.so.1 => /usr/lib64/libaio.so.1 (0x00002b497fa42000)
[oracle@localhost ~]$ /usr/bin/nm $ORACLE_HOME/bin/oracle | grep io_getevent
w io_getevents@@LIBAIO_0.4
proc文件系统包含了两个虚拟文件,它们可以用来对异步 I/O的性能进行优化:
/proc/sys/fs/aio-nr文件提供了系统范围异步 I/O请求现在的数目。
/proc/sys/fs/aio-max-nr文件是所允许的并发请求的最大个数。最大个数通常是 64KB,这对于大部分应用程序来说都已经足够了。
检查异步I/O是否在使用
根据[Note 370579.1],可以通过查看slabinfo统计信息查看操作系统中AIO是否运行,slab是Linux的内存分配器,AIO相关的内存结构已经分配,kiocb值的第二列和第三列非0即是已使用。与kernel 2.4.x不同,没有显示kiobuf,因为从kernel 2.5.43开始,kiobuf已经从内核中被移除。
kioctx:
AIO上下文在内核空间对应数据结构kioctx,它保存异步IO的所有信息:
[root@localhost datadp]# grep kio /proc/slabinfo
kioctx 35 84 320 12 1 : tunables 54 27 8 : slabdata 7 7 0
kiocb 0 0 256 15 1 : tunables 120 60 8 : slabdata 0 0 0
--以上为我数据库没有设置filesystemio_options参数以前的一个状态,当我设置该参数后查看如下,再次测试将一个8G左右的表insert的时候:
SQL> alter system set filesystemio_options=setall scope=spfile; System altered. SQL> shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. SQL> startup SQL> sho parameter filesystemio_options NAME TYPE VALUE ------------------------------------ ----------- ---------------------------- filesystemio_options string SETALL
[root@localhost datadp]# grep kio /proc/slabinfo
kioctx 26 60 320 12 1 : tunables 54 27 8 : slabdata 5 5 0
kiocb 165 165 256 15 1 : tunables 120 60 8 : slabdata 11 11 2
[root@localhost datadp]# grep kio /proc/slabinfo
kioctx 35 60 320 12 1 : tunables 54 27 8 : slabdata 5 5 0
kiocb 338 420 256 15 1 : tunables 120 60 8 : slabdata 28 28 188
如上可以发现系统有异步I/O在使用了
检查系统IO情况,发现虽然也是100%,但写入新能从原来的2M提高到130M/S左右,此时I/O的性能大大的提高了。通过时间对比同样是8000W的记录修改后执行时间提高了7倍多。
avg-cpu: %user %nice %system %iowait %steal %idle
0.50 0.00 1.00 22.35 0.00 76.15
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.00 20038.00 2.00 353.00 8.00 103716.00 584.36 132.62 390.83 2.82 100.10
sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda5 0.00 20038.00 2.00 353.00 8.00 103716.00 584.36 132.62 390.83 2.82 100.10
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc 39.00 0.00 162.00 0.00 10380.00 0.00 128.15 1.13 7.04 2.01 32.50
sdc1 39.00 0.00 162.00 0.00 10380.00 0.00 128.15 1.13 7.04 2.01 32.50
avg-cpu: %user %nice %system %iowait %steal %idle
0.13 0.00 7.51 40.55 0.00 51.81
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.00 38869.00 2.00 522.00 8.00 156856.00 598.72 143.07 277.58 1.91 100.10
sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda5 0.00 38869.00 2.00 522.00 8.00 156856.00 598.72 143.07 277.58 1.91 100.10
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
查看statspack的报告:
Top 5 Timed Events Avg %Total
~~~~~~~~~~~~~~~~~~ wait Call
Event Waits Time (s) (ms) Time
----------------------------------------- ------------ ----------- ------ ------
log file switch (checkpoint incomplete) 15 802 53444 29.2
db file async I/O submit 27,298 560 21 20.4
log file parallel write 5,354 317 59 11.6
db file scattered read 5,567 267 48 9.7
db file parallel write 31,696 214 7 7.8
-------------------------------------------------------------
同样发现虽然有db file async I/O submit 的等待事件,但可以发现平均每个等待只为21ms,大大降低了,说明很有效。
也就是说系统默认情况下,是走系统的caches来和数据库文件进行数据传输。但由于系统BUG,当请求异步IO的时候出现了严重的等待,我们关闭异步IO查看DML性能情况。
SQL> alter system set disk_asynch_io=false scope=spfile; System altered. SQL> alter system set filesystemio_options=none scope=spfile; System altered. SQL> startup force
清空缓存:
ALTER SYSTEM FLUSH SHARED_POOL;
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH GLOBAL CONTEXT;
SQL > insert /*+position(t1,4)*/ into t1 select /*+position(t2,4)*/ * from t2 nolongging;
查看I/O状况,发现此时系统I/0被占满
avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 0.12 12.38 0.00 87.50
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.00 422.00 2.00 186.00 8.00 2372.00 25.32 1.13 5.96 5.30 99.60
sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda5 0.00 422.00 2.00 186.00 8.00 2372.00 25.32 1.13 5.96 5.30 99.60
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdc1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
可以发现sda5使用率100%,且只有2M多一些的写入量。statspack报告中出现大量的db file parallel write等待事件,说明虽然没有了异步IO的等待事件,但I/O的性能却急剧下降。
补充:
1、使用操作系统的caches
操作系统和设备控制器提供了数据库缓存,这些不直接与数据库的缓存管理相冲突。尽管如此,这些架构可能消耗资源当有很少的或没有性能利益。当数据库文件存储在Linux或者UNIX文件系统上时,这种情况就显而易见了。默认情况下,所有的数据库I/O都要通过文件系统的缓存。
在一些Linux和UNIX系统上,直接I/O是可用的对于文件存储来说。这个协议允许数据库文件存取在文件系统范围内,绕过文件系统缓存。直接的I/O节约了CPU资源斌并且允许文件系统缓存是独立的在没有数据库活动的时候,例如program texts 和spool files.
尽管操作系统的的cache经常是冗余的因为数据库的cache buffers blocks。在一些情况下,数据库不能用database buffer cache。在这些情况下,使用直接I/O或者裸设备可能产生更严重的性能问题比使用系统的buffer。例如
· Reads or writes to the TEMP tablespace
· Data stored in NOCACHE LOBs
· Parallel Query slaves reading data
2、同步IO和异步IO的区别:
在同步文件IO中,线程启动一个IO操作然后就立即进入等待状态,直到IO操作完成后才醒来继续执行。
而异步文件IO方式中,线程发送一个IO请求到内核,然后继续处理其他的事情,内核完成IO请求后,将会通知线程IO操作完成了。
如果IO请求需要大量时间执行的话,异步文件IO方式可以显著提高效率,因为在线程等待的这段时间内,CPU将会调度其他线程进行执行,如果没有其他线程需要执行的话,这段时间将会浪费掉(可能会调度操作系统的零页线程)。如果IO请求操作很快,用异步IO方式可能更低效,此时同步IO方式会较优。
同步IO在同一时刻只允许一个IO操作,也就是说对于同一个文件句柄的IO操作是序列化的,即使使用两个线程也不能同时对同一个文件句柄同时发出读写操作。重叠IO允许一个或多个线程同时发出IO请求。
异步IO在请求完成时,通过将文件句柄设为有信号状态来通知应用程序,或者应用程序通过GetOverlappedResult察看IO请求是否完成,也可以通过一个事件对象来通知应用程序。
3、相关参数介绍
在oracle里为了提高io的速度,常用参数db_writer_processes和 dbwr_io_slaves
在数据库里事务数非常高,或db cache很大,一个DBWn process跟不上数据的load,我们可以调整这两个参数,这两个参数的作用就是增加io读写进程,启用异步io,加快io的速度
多个 slaves 可以并行写数据文件,而多个dbwr也可以并行写数据文件
一个 dbwr 多个 slaves是 dbwr搜集dirty buffer而 slaves写数据文件
多个dbwr 可以并行地搜集dirty buffer 并且并行地写数据文件
但是如果系统支持AIO一般不用设置多dbwr 或者 io slaves
db_writer_processes:在多cpu,多磁盘的环境,一般是每8个cpu一个dbwr进程
什么时候配置这两个参数
如果系统的io是瓶颈是,检查os是否支持异步io,如果支持异步io,但目前没有使用,那就启用异步io来缓解io瓶颈。如果os不支持异步io,
或os已经启用异步io,但io还是瓶颈,那我们可以配置多个dbwr进程。配置这两个参数是要注意,大都是如下
一个db_writer_processes,多个dbwr_io_slaves
多个db_writer_processes,dbwr_io_slaves不启用
如需转载请署名出处:
************************************************************************************************
* Auther : Paladin *
* Blog :http://blog.csdn.net/jyjxs *
********************************************************************************************************************