问题描述:
在大批量同步、抽取数据的过程中,往往出现表空间扩展失败、一些很长时间未执行完的SQL,分布式等待锁等。下面就来看看如何解决这些问题。
查询时间较长的SQL并杀掉应用层回话
oracle数据库查询正在执行的sql,通过gv$ session 和gv$sqlarea两个视图:
select n.sid,n.serial#,n.program,n.terminal,n.logon_time,n.machine,n.sql_id,a.sql_text from gv$session n,gv$sqlarea a where n.sql_id=a.sql_id order by logon_time;
或者指定查询alter开头的sql:
select n.sid,n.serial#,n.program,n.terminal,n.logon_time,n.machine,n.sql_id,a.sql_text from gv$session n,gv$sqlarea a where n.sql_id=a.sql_id and a.sql_text like 'alter%' order by logon_time;
杀应用会话命令:(把上面命令查询到的sid和serial#填写到下面的语句中)
alter system kill session 'sid,serial#' immediate;
关于“ORA-02049: 超时: 分布式事务处理等待锁”的原因和解决办法
【问题思路】:
(1)首先我在数据库中刚查过数据(印刷流水号),sql为:
select visaserialno, businessno,visacode, visaname, usercode, visastatus, comcode from vsmark
where visacode like 'DAC051A32007A(山东)' and usercode='02110003' for update;
(2)然后在核心系统中输入查询的印刷流水号visaserialno,在核心系统中调用接口出现 ORA-02049: 超时: 分布式事务处理等待锁 的错误。
(3)我怀疑是因为上述sql只for update而没有提交事务(commit),数据库事务你没有commit或者rollback导致事务不能统一提交。导致把错误回传给客户端让其处理。因为核心系统用的数据库和我更改的数据库是一致的。
(4)然后我把本地数据库commit,再在核心系统中调用接口。成功。
【总结】:
该参数指定等待分布式锁资源的时间,超过这个时间事务自动回滚,即在等待未释放的资源超过一定的时间,系统自动报错给客户端,就会以ORA-02049: 超时: 分布式事务处理等待锁 的方式提错给你。该值默认为60,即等待分布式锁资源60秒。从上面的测试来看,使用dblink做分布式事务时一定要及时commit或rollback,尽量在分布式应用中使用短事务为宜。dblink 作用就是让数据库中的数据负载均衡,一般情况下数据量较大的数据都会用到。
表空间扩展失败
查看用户所在表空间
数据字典中用户表:dba_users;
通过数据字典查看有多少个用户:select username from dba_users;
数据字典中表空间表: dba_tablespaces;
查看有几个表空间:select tablespace_name from dba_tablespaces;
oracle 查看用户所在的表空间:select username,default_tablespace from dba_users order by username;
-----查看表空间使用情况------
SELECT UPPER(F.TABLESPACE_NAME) "表空间名",
D.TOT_GROOTTE_MB "表空间大小(M)",
D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') "使用比",
F.TOTAL_BYTES "空闲空间(M)",
F.MAX_BYTES "最大块(M)"
FROM (SELECT TABLESPACE_NAME,
ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES
FROM SYS.DBA_FREE_SPACE
GROUP BY TABLESPACE_NAME) F,
(SELECT DD.TABLESPACE_NAME,
ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB
FROM SYS.DBA_DATA_FILES DD
GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER BY 4 DESC;
--查看表空间是否具有自动扩展的能力
SELECT T.TABLESPACE_NAME,D.FILE_NAME,
D.AUTOEXTENSIBLE,D.BYTES,D.MAXBYTES,D.STATUS
FROM DBA_TABLESPACES T,DBA_DATA_FILES D
WHERE T.TABLESPACE_NAME =D.TABLESPACE_NAME
ORDER BY TABLESPACE_NAME,FILE_NAME;
-修改表空间文件扩展方式:
ALTER DATABASE
DATAFILE '/u01/Oracle/oradata/orcl/ccen01.dbf' AUTOEXTEND
ON NEXT 50M MAXSIZE UNLIMITED
增加表空间大小的四种方法
Meathod1:
给表空间增加数据文件
ALTER TABLESPACE app_data ADD DATAFILE
'D:\ORACLE\PRODUCT\10.2.0\ORADATA\EDWTEST\APP03.DBF' SIZE 50M;
Meathod2:新增数据文件,并且允许数据文件自动增长
ALTER TABLESPACE app_data ADD DATAFILE
'D:\ORACLE\PRODUCT\10.2.0\ORADATA\EDWTEST\APP04.DBF' SIZE 50M
AUTOEXTEND ON NEXT 5M MAXSIZE 100M;
Meathod3:允许已存在的数据文件自动增长
ALTER DATABASE DATAFILE 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\EDWTEST\APP03.DBF'
AUTOEXTEND ON NEXT 5M MAXSIZE 100M;
Meathod4:手工改变已存在数据文件的大小
ALTER DATABASE DATAFILE 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\EDWTEST\APP02.DBF'
RESIZE 100M;
ORA-30036:无法按8扩展段(在还原表空间xxx中)
1.什么是还原表空间?
还原表空间即Undo表空间,是Oracle特有的概念,Undo表空间会自动分配Undo段,用来保存事务中DML( Insert、Update或Delete)语句的Undo数据。在Oracle9i前,管理Undo数据只能使用Rollback Segment。从Oracle9i开始,管理Undo数据不仅可以使用回滚段,还可以使用Undo表空间。而由于管理里规划回滚段太过复杂,Oracle10g已经弃用回滚段,仅使用Undo表空间来管理Undo数据。
2.什么是Undo数据?
Undo数据也称回滚数据,当执行DML语句时,事务操作过程中的数据被称为Undo数据,主要有两个作用:
确保事务一致性:如果事务发生错误或者用户想要取消数据库操作,则可以通过Rollback回到修改前的值。
提供一致性读:如表T有100条记录,用户A在表T执行了语句删除掉10条记录,尚未提交,此时用户B执行查询语句,将返回100条记录而不是90条。
3.如何解决?
言归正传,开始解决问题,首先我们查看当前实例使用的Undo表空间:
SQL> show parameter undo;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
可以看到,使用的Undo表空间为“UNDOTBS1”,与报错内容中的名字一致。接下来查看数据库可用的Undo表空间:
SQL> SELECT tablespace_name FROM dba_tablespaces WHERE contents='UNDO';
TABLESPACE_NAME
------------------------------
UNDOTBS1
UNDOTBS2
结果显示有两个Undo表空间可用,分别为UNDOTBS1、UNDOTBS2。我们来看看这两个表空间的使用情况:
-----查看表空间使用情况------
SELECT UPPER(F.TABLESPACE_NAME) "表空间名",
D.TOT_GROOTTE_MB "表空间大小(M)",
D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') "使用比",
F.TOTAL_BYTES "空闲空间(M)",
F.MAX_BYTES "最大块(M)"
FROM (SELECT TABLESPACE_NAME,
ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES
FROM SYS.DBA_FREE_SPACE
GROUP BY TABLESPACE_NAME) F,
(SELECT DD.TABLESPACE_NAME,
ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB
FROM SYS.DBA_DATA_FILES DD
GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER BY 4 DESC;
可以看到,UNDOTBS1有两个数据文件来存储Undo数据,使用率都到达了90%以上,所剩空间已不足
解决的办法有三个:
1.为表空间增加数据文件
alter tablespace UNDOTBS1
add datafile '+DATADG/esbmssdb/datafile/undotbs1.4.dbf' --数据文件名
size 100M --初始大小
autoextend on next 1M maxsize 8192M; --自增,每次增加1M,最大为8192M
2.设置文件自动扩展
alter database
datafile '+DATADG/esbmssdb/datafile/undotbs1.3.dbf'
autoextend on next 1M maxsize 8192M;
3.切换Undo表空间
alter system set undo_tablespace = UNDOTBS2;
注:如果数据库中只有一个可用的Undo表空间,则使用前两种方法。