数据库收缩数据文件的尝试(三)(r11笔记第22天)

 
不知道大家在数据库运维中是否会有这样的困扰,一个数据文件里没有多少数据,但是数据文件的大小却调不下来,尝试使用resize来调整屡屡失败。如果一个数据文件里有很多的小表,存在大量这样的碎片表,虽然我们从前端看不到,但是如果查看存储结构就会发现还是挺混乱的。

    本质上来说,Oracle也不希望我们去刻意处理这些物理存储方面的设置,比如设定某个表一定存放在某个数据文件里,一个表空间里存在10个数据文件,一条insert语句运行下去,到底数据进了哪个数据文件,应该不需要DBA刻意去关心,而且Oracle也没提供这样的数据字典来告诉你,所以我们查看的最细粒度的存储数据字典是dba_extents,而没有db_blocks当然Oracle给了你一把钥匙,那就是ROWID。通过ROWID我们可以得到很多未曾发现的问题和可能性。

    我们换一个问法,在一个事务中是否会改变ROWID?

如果是普通的增删改操作,基于主键,基于数据变化,肯定是无法改变ROWID,因为ROWID本身就是一个伪列,这个伪列的效果本质上其实比主键还要给力,查询效率还要高。

    如果我要做这样一个操作,表test的数据量不大在5万条,分布在6,7,8三个数据文件上,如果我们新建一个数据文件9,希望把这些数据都迁移到9号数据文件,而且希望保证高可用的情况下,是否可以实现?

   在这个场景中,我们就可以充分利用ROWID来玩一玩了。

我们创建一个临时中转的表,比如表名为test,则中转的临时表为tmp_test

把表test在8号数据文件里的数据筛查出来插入临时的中转表tmp_test

insert into  test.tmp_test  select * from test.test where dbms_rowid.rowid_relative_fno(rowid)=8
100 rows created.然后删除已有的表test在8号数据文件的数据delete from test.test where dbms_rowid.rowid_relative_fno(rowid)=8;
100 rows deleted.注意此处,这里是一个事务,对于事务外的应用数据的查询还是可以满足一致性的需求。
但是因为表里的数据量很小,所以这个过程造成的阻塞时间会很短。

然后把数据插入

insert  /*+append*/ into  mbi.test select *from test.tmp_test;
100 rows created.

完成之后就是提交commit

当然如果我们要求数据要放在指定的数据文件里,而不是根据数据的增长情况增量的放置,可以使用allocate的方式来处理,比如指定数据放入9号数据文件中。

alter table  test allocate extent (size 1M datafile  '/U01/app/oracle/oradata/test/test_data09.dbf');

操作之后还是需要验证一下,原来的数据文件里确实是不存在那些数据了。

select count(*)  from test.test where dbms_rowid.rowid_relative_fno(rowid)=8;
  COUNT(*)
----------
         0

这些数据还是在临时的表里可以查到,确认无误之后就可以直接drop了。

select count(*)  from test.tmp_test;
  COUNT(*)
----------
        100当然一个数据库的数据量非常大,存在上百个这样的数据文件有没有什么简洁的方法来统一处理呢。其实是有的。采用的思路就是今天分享的内容,不过后面补充了一些更多的验证和场景补充。能够达到的一个基本效果就是可以一键式部署,感兴趣可以私聊,我近期也会把脚本开放出来。

时间: 2024-07-30 05:42:32

数据库收缩数据文件的尝试(三)(r11笔记第22天)的相关文章

数据库收缩数据文件的尝试(二)(r11笔记第9天)

在之前自己的一个测试环境中,因为本身磁盘空间不足,导致一个测试库数据目录溢出,最后花了点功夫,将一个2G左右的文件经过收缩的操作后,竟然收缩为7M.详情可以参考 收缩关于收缩数据文件的尝试(r5笔记第34天)     而隔了很长一段时间后,我在线上一个环境碰到了类似的问题. 这个数据库是一个OLAP的业务库,之前的数据量还不小,大概有1.7T,但是经过业务梳理之后,有一部分业务不需要的数据就删除了,后续迁移了另外一个环境的数据过来.     从资源的规划来看,这个库的数据增长还远远达不到目前的使

关于收缩数据文件的尝试

在数据库中对于数据文件都是提前规划,不够就加的情况,很少会留意到其实有些数据文件那么大,其实条件允许也是可以收缩收缩的. 这种情况在本地测试环境中尤为突出,本来就用虚拟机跑个数据库,硬盘空间就够紧张,几十M几百M都是空间,都得"兆兆"计较. 今天在做dataguard的练习的时候,发现主库中的数据文件有些大,差不多4G左右,其实这个库里也没有装什么特别的东西,都是些测试表,完全可以清楚,使用dba_segments查看了下,有一个测试表在2G左右,占了不少的空间,基本一个数据文件都占完

Sql数据库MDF数据文件数据库恢复

EXEC sp_attach_db @dbname = 'dbname', @filename1 = 'd:\dbname_Data.MDF', @filename2 = 'd:\dbname_log.ldf'  sp_attach_single_file_db @dbname = 'dbname' , @physname = 'physical_name' dbname:即要还原的数据库名字. Physname:即物理文件名. Physical_name:即.mdf文件路径. 数据库 : ms

假期前的数据库检查脚本之主备关系(r11笔记第46天)

   快过年了,很多系统都要进入最后的检查和复验阶段,一方面在节假日前,提前发现问题总比过节的时候发现要好.另一方面如果出现故障的时候能及时进行处理,这个时候我们就需要有一个尽可能全面的元数据收集.而且还有一点比较重要的就是工作交接,如果你临时有事,需要让同事来代劳,你得提供清晰易懂的信息给他们.    可能有的同学会觉得我们已经有了数据库监控,基本的性能分析,这个工作是不是就可以忽略了.监控只是标记状态,出现问题时候它没法帮你处理,还是需要人工介入,而人工介入尽可能全面的信息就是这些元数据了,

收缩Oracle数据文件

      最近有网友提到收缩Oracle数据文件的问题,这是DBA经常碰到的一个常见问题.通常我们需要收缩相应的数据文件以减少来自磁盘空间的压力以及提高数据库的整体性能.但这并非对于所有情形都是适用的,尤其是生产环境.因为生产环境数据清洗相当较少,因此空间浪费也比较小,而且一旦收缩之后又要重新自动扩展数据文件,浪费系统资源.对于UAT,DEV环境,多DB,磁盘空间压力大的情形,收缩一下非常有必要.勒紧裤带过日子也是常有的事情,哈哈.总之收缩数据文件会使得磁盘空间得以释放以及加快数据迁移,RMA

Oracle的数据库、表空间及数据文件简介

数据文件是数据库的物理存储单位,而表空间TableSpace则是数据库的逻辑组成部分.数据库的数据是存储在表空间中的,而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间.一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行. 数据库,表空间,数据文件是紧密关联的,但它们有着重要的区别: 数据库和表空间 一个Oracle数据库由一个或多个叫做表空间的逻辑存储单元组成,表空间存储了所有数据库的数据. 表空间和数据文件 在Or

Oracle某个数据文件损坏,如何打开数据库

oracle|数据|数据库 某个数据文件损坏,如何打开数据库? 系统环境: 1.操作系统:Windows 2000 Server,机器内存128M2.数据库: Oracle 8i R2 (8.1.6) for NT 企业版3.安装路径:C:\ORACLE 错误现象: 因误操作,数据库中某一数据文件被误删,控制面板的Oracle相关服务显示已启动,但用SQL*Plus无法连接,显示以下错误ORA-01033: ORACLE initialization or shutdown in progres

如何从完好的数据文件恢复oracle数据库

一.有数据文件.控制文件和日志文件的备份1.服务器重装了操作系统,oracle也重装了.如果重装的oracle和以前损坏的数据库是一模一样的结构,那么此时的恢复是比较简单的. 1)删除掉新建数据库的所有数据文件.控制文件和日志文件.Copy原数据库的数据文件.控制文件和日志文件到对应目录下. 2) Cmd>sqlplus /nolog Sql>conn as sysdba 用户名:system 密码:(此处密码为新创建数据库的密码) Sql>shutdown immediate Sql&

SQL Server 2008 数据库误删除数据的恢复

原文:SQL Server 2008 数据库误删除数据的恢复 原文:http://www.cnblogs.com/dudu/archive/2011/10/15/sql_server_recover_deleted_records.html SQL Server中误删除数据的恢复本来不是件难事,从事务日志恢复即可.但是,这个恢复需要有两个前提条件: 1. 至少有一个误删除之前的数据库完全备份. 2. 数据库的恢复模式(Recovery mode)是"完整(Full)". 针对这两个前提