
问题现象:
技术交流群里有位朋友反馈在对Oracle数据库执行添加数据文件(30G大小)操作时,报错如下,数据库版本19C:
ORA-19502: write error on file "/xxx/xxx.dbf", block number xxxxx (block size=8192)ORA-27072: File I/O error
问题分析:
创建表空间和添加数据文件属于基础操作,本以为分分钟搞定的问题,却一时间难住了众多大佬。
首先排查磁盘空间剩余容量,df -h,df -i检查空间、inode非常充足,远远大于30GB。
这时有位大佬提出一个非常有价值的建议,他怀疑df -h看到的磁盘空间并不准确,比如虚拟机上看到的剩余磁盘空间还有100GB,但实际虚拟机所在宿主机物理磁盘只有2GB可用空间,这时超过2GB的数据肯定是无法写入的,建议使用cp命令拷贝一个大文件到数据文件目录,经测试文件确实无法写入,提示:No space left on device ,显然df -h看到可用空间,远远小于实际可用空间。
但这位朋友反馈,并没有使用虚拟机,使用的是物理机,那么还有什么原因会导致df -h数据不准确呢,之前遇到过nas存储查看空间使用率不准确。还有带有特殊压缩功能的存储不准确,但这种情况大多数实际可用空间大于df -h显示的可用空间。
这时另一个大佬提出了一个非常重要的概念:“精简卷”,最终也定位到确实是这个精简卷导致的问题,很显然,又触到我的知识盲区了。

到底什么是“精简卷呢”?
redhat官网有详细介绍,相关链接如下:
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/8/html/configuring_and_managing_logical_volumes/creating-and-managing-thin-provisioned-volumes_configuring-and-managing-logical-volumes
第 11 章 创建和管理精简配置的卷(精简卷)
Red Hat Enterprise Linux 支持精简配置的快照卷和逻辑卷。
逻辑卷和快照卷可以是精简配置的:
使用精简配置的逻辑卷,您可以创建大于可用物理存储的逻辑卷。
使用精简配置的快照卷,您可以在同一数据卷中存储更多虚拟设备。
###看上去很不错的功能,是不是要谢谢你呢?###

11.1. 精简配置概述
很多现代存储堆栈现在提供在密集配置和精简配置之间进行选择的能力:
密集配置提供了块存储的传统行为,其中块的分配与其实际用途无关。
精简配置允许置备更大的块存储池,其大小可能大于存储数据的物理设备,从而导致过度配置。
过度置备可能是因为单个块在实际使用之前没有被分配。
如果您有多个共享同一池的精简置备设备,那么这些设备可以是过度配置的。
通过使用精简配置,您可以超额使用物理存储,且可以管理称为精简池的可用空间池。
当应用程序需要时,您可以将这个精简池分配给任意数量的设备。
当需要有效分配存储空间时,您可以动态扩展精简池。
例如,如果 10 个用户的每个用户都为他们的应用程序请求一个 100GB 的文件系统,那么您可以为每个用户创建一个 100GB 的文件系统,但其由较少的实际存储支持,仅在需要时使用。
注意
在使用精简配置时,监控存储池,并在可用物理空间耗尽时添加更多容量是非常重要的。
以下是使用精简配置的设备的一些优点:
1.您可以创建大于可用物理存储的逻辑卷。2.您可以将更多的虚拟设备存储在相同的数据卷中。3.您可以创建逻辑上可自动增长的文件系统,以支持数据需求,并将未使用的块返回给池,以供池中的任意文件系统使用。
以下是使用精简配置的设备的潜在缺陷:
1.精简配置的卷存在耗尽可用物理存储的固有风险。如果过度配置了底层存储,您可能会因为缺少可用物理存储而导致停机。
例如,如果您创建了 10T 的精简配置的存储,而只有 1T 的物理存储来支持,则卷将在 1T 耗尽后不可用或不可写。
2.如果卷在精简配置的设备后没有向层发送丢弃,那么对使用情况的统计将不准确。
例如,在不使用 -o discard mount 选项的情况下放置文件系统,且不在精简配置的设备之上定期运行 fstrim,则永远不会不分配之前使用的存储。在这种情况下,随着时间的推移,即使没有真正使用它,您最终都会使用全部的置备量。您必须监控逻辑和物理使用情况,以便不会用尽可用的物理空间。在带有快照的文件系统上,写时复制(CoW)操作可能会较慢。数据块可以在多个文件系统之间混合,导致底层存储的随机访问限制,即使它没有向最终用户展示那种方式。
精简卷测试过程:
测试数据库:Oracle 11.2.0.4.0操作系统:Red Hat Enterprise Linux Server release 7.5 (Maipo)
新增加一个2GB大小的磁盘
[root@cjc-db-01 ~]# lsblksdb 8:16 0 2G 0 disk
[root@cjc-db-01 ~]# fdisk -lDisk dev/sdb: 2147 MB, 2147483648 bytes, 4194304 sectorsUnits = sectors of 1 * 512 = 512 bytesSector size (logical/physical): 512 bytes 512 bytesI/O size (minimum/optimal): 512 bytes 512 bytes
创建PV
pvcreate dev/sdbPhysical volume "/dev/sdb" successfully created.
创建VG
vgcreate vg_chenjch /dev/sdbVolume group "vg_chenjch" successfully created
创建精简池
[root@cjc-db-01 ~]# lvcreate -L 1G -T vg_chenjch/mythinpoolThin pool volume with chunk size 64.00 KiB can address at most 15.81 TiB of data.Logical volume "mythinpool" created.
创建精简卷
[root@cjc-db-01 ~]# lvcreate -V 100G -T vg_chenjch/mythinpool -n thinvolumeWARNING: Sum of all thin volume sizes (100.00 GiB) exceeds the size of thin pool vg_chenjch/mythinpool and the size of whole volume group (<2.00 GiB).WARNING: You have not turned on protection against thin pools running out of space.WARNING: Set activation/thin_pool_autoextend_threshold below 100 to trigger automatic extension of thin pools before they get full.Logical volume "thinvolume" created.
可以看到,总磁盘大小2GB,分配1GB给精简池,从精简池中又分配100GB的空间给精简卷,远大于磁盘、VG、精简池的大小,从而导致了df -h数据不准确。

查看创建的精简池和精简卷
[root@cjc-db-01 soft]# lvs -a -o +devicesLV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert Devicesswap ol -wi-ao---- 2.00g /dev/sda2(0)[lvol0_pmspare] vg_chenjch ewi------- 4.00m /dev/sdb(0)mythinpool vg_chenjch twi-aotzM- 1.00g 100.00 13.67 mythinpool_tdata(0)[mythinpool_tdata] vg_chenjch Twi-ao---- 1.00g /dev/sdb(1)[mythinpool_tmeta] vg_chenjch ewi-ao---- 4.00m /dev/sdb(257)thinvolume vg_chenjch Vwi-aotz-- 100.00g mythinpool 1.00root vg_cjc -wi-ao---- <46.99g /dev/sda3(0)
[root@cjc-db-01 soft]# lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 50G 0 disk├─sda1 8:1 0 1G 0 part /boot├─sda2 8:2 0 2G 0 part│ └─ol-swap 249:1 0 2G 0 lvm [SWAP]└─sda3 8:3 0 47G 0 part└─vg_cjc-root 249:0 0 47G 0 lvm /sdb 8:16 0 2G 0 disk├─vg_chenjch-mythinpool_tmeta 249:2 0 4M 0 lvm│ └─vg_chenjch-mythinpool-tpool 249:4 0 1G 0 lvm│ ├─vg_chenjch-mythinpool 249:5 0 1G 0 lvm│ └─vg_chenjch-thinvolume 249:6 0 100G 0 lvm /oradata└─vg_chenjch-mythinpool_tdata 249:3 0 1G 0 lvm└─vg_chenjch-mythinpool-tpool 249:4 0 1G 0 lvm├─vg_chenjch-mythinpool 249:5 0 1G 0 lvm└─vg_chenjch-thinvolume 249:6 0 100G 0 lvm /oradatasr0 11:0 1 1024M 0 romloop0 7:0 0 4.1G 0 loop /mnt
可以看到,sdb磁盘总大小2GB,下面的卷100GB。
sdb 8:16 0 2G 0 diskvg_chenjch-thinvolume 249:6 0 100G 0 lvm /oradata
格式化
[root@cjc-db-01 ~]# mkfs -t xfs /dev/mapper/vg_chenjch-thinvolumemeta-data=/dev/mapper/vg_chenjch-thinvolume isize=256 agcount=16, agsize=1638400 blks= sectsz=512 attr=2, projid32bit=1= crc=0 finobt=0, sparse=0data = bsize=4096 blocks=26214400, imaxpct=25= sunit=16 swidth=16 blksnaming =version 2 bsize=4096 ascii-ci=0 ftype=1log =internal log bsize=4096 blocks=12800, version=2= sectsz=512 sunit=16 blks, lazy-count=1realtime =none extsz=4096 blocks=0, rtextents=0
挂载
[root@cjc-db-01 ~]# mkdir /oradata[root@cjc-db-01 ~]# mount /dev/mapper/vg_chenjch-thinvolume /oradata
查看可用空间,显示100G。

[root@cjc-db-01 ~]# df -h /oradata/Filesystem Size Used Avail Use% Mounted on/dev/mapper/vg_chenjch-thinvolume 100G 33M 100G 1% /oradata
授权
[root@cjc-db-01 ~]# chown oracle:oinstall /oradata
创建表空间,数据文件大小800MB
SQL> create tablespace cjc datafile '/oradata/cjc_tbs01.dbf' size 800M;Tablespace created.
添加数据文件,在添加一个800MB数据文件
由于1600MB大于1GB,所以添加失败。
SQL> alter tablespace cjc add datafile '/oradata/cjc_tbs02.dbf' size 800M;alter tablespace cjc add datafile '/oradata/cjc_tbs02.dbf' size 800M*ERROR at line 1:ORA-01119: error in creating database file '/oradata/cjc_tbs02.dbf'ORA-27052: unable to flush file dataLinux-x86_64 Error: 5: Input/output errorAdditional information: 1
错误号和那位朋友遇到的不同,他的错误号是ORA-19502、ORA-27072,我模拟出的错误号是ORA-01119,ORA-27052,不清楚是因为数据库版本还是其他什么原因导致错误号不一样,简单看下相关错误号说明。
[oracle@cjc-db-01 oradata]$ oerr ora 0111901119, 00000, "error in creating database file '%s'"// *Cause: Usually due to not having enough space on the device.// *Action:[oracle@cjc-db-01 oradata]$ oerr ora 2705227052, 00000, "unable to flush file data"// *Cause: fsync system call returned error, additional information// indicates which function encountered the error// *Action: check errno
[oracle@cjc-db-01 oradata]$ oerr ora 1950219502, 00000, "write error on file \"%s\", block number %s (block size=%s)"// *Cause: write error on output file// *Action: check the file[oracle@cjc-db-01 oradata]$ oerr ora 2707227072, 00000, "File I/O error"// *Cause: read/write/readv/writev system call returned error, additional// information indicates starting block number of I/O// *Action: check errno
虽然df -h显示还有大量可用空间,由于精简卷的原因,可用空间并不准确。
[root@cjc-db-01 soft]# df -h /oradata/Filesystem Size Used Avail Use% Mounted on/dev/mapper/vg_chenjch-thinvolume 100G 833M 100G 1% /oradata
为了少踩坑,请远离“精简卷”。
###chenjuchao 20240120###




