Oracle
名词介绍
数据库
oracle数据的物理存储,包括数据文件、参数文件、日志等
实例
一个oracle实例有一系列的后台进程,一个数据库可以有n个实例。就好比说可以跑多个QQ一样
表空间
是数据文件(ora/dbf)的逻辑映射,也就是多个数据文件组成一个表空间,数据文件是看得见摸得着的文件,表空间是一个逻辑概念。
--创建表空间 create tablespace 表空间名称 datafile 'c:\app\gen\oradata\myora\xxx.dbf' size 表空间初始大小100m Autoextend on; (自增长) --查看已经创建好的表空间(创建完用户后才能看到刚才创建好的表空间) select default_tablespace,temporary_tablespace,d.username from dba_users d
用户
用户使操作表的基本单位,相当于mysql中的数据库database。不同实例可以创建多个用户。
--创建用户 create user 用户名 identified by 密码 default tablespace 表空间名称 temporary tablespace temp;
权限
有了用户,要想使用用户账号管理自己的表空间,还需要给它权限
--给用户授予登录/创建表/管理员的权限 grant connect/resource/dba to 用户名; --给用户授予其他用户的表权限 grant select/delete/update/insert on 其他用户名.表名 to 用户名; --取消用户权限 revoke 权限 from 用户名;
设置同义词
oracle里,用户A要访问用户B的表需要带用户B的前缀,使用不便,可以使用同义词解决
--使用dba用户授权创建同义词 grant CREATE SYNONYM to jwxtzzjg; --创建同义词 create synonym gf_zzjgdygxb for idc_data_sharedb.gf_zzjgdygxb;
数据文件
数据库的物理存储单位。数据库的数据是存储在表空间中的,真正是在某一个或多个数据文件中。
windows安装
此处以oracle 11g为例
- 取消安全更新
- 创建和配置数据库
- 服务器类
- 单实例数据库安装
- 高级安装
- 简体中文、英语
- 企业版
- 安装目录
- 一般用途/事务处理
- 数据库名(一般根据实际用途取名,如ecard)
- 内存(根据现场配,默认40%),字符集(默认gbk)
- 管理选项(下一步)
- 文件系统(根据现场指定数据库存放位置)
- 不启动自动备份
- 对所用账户使用相同的口令(大小写数字都要有,最少八位)
- 保存响应文件(保存设置)
- 安装ing
- 确定 完成
登录
在oracle服务端登录oracle的方法https://blog.csdn.net/heshushun/article/details/79773886
启动
- 先登录服务器后,切换到oracle用户状态下: su - oracle
- 检查oracle监听器运行状态: lsnrctl status命令查看。
- 若没启动,执行启动监听,通过命令: lsnrctl start (lsnrctl stop 关闭监听)
- 管理员 sysdba 权限登陆oracle: sqlplus / as sysdba
- 启动服务(实例): startup
关闭
sql> shutdown immediate; --如果长时间没反应,因为有大事务要回滚,导致数据库一直在等待
回滚执行完成,ctrl+c取消
sql> alter system checkpoint; --设置检查点。一般在shutdown前,为了防止类似情况发生而
丢失数据
sql> shutdown abort; --强制关闭数据库
重启
SQL> shutdown immediate
SQL> startup
检验服务是否开启
在oracle客户端登录oracle的方法
原始的登录方法
sqlplus scott/123@//192.168.94.133/orcl //192.168.94.133是服务端的IP地址
修改配置文件后的登录方法
sqlplus scott/123@orcl_133
可以理解为“orcl_133”是“//192.168.94.133/orcl”的别名,这个别名是在客户端软件(sqlplus)的安装目录下配置文件设置的。如E:\app\Administrator\product\11.2.0\client_1\network\admin\tnsnames.ora
这里以服务端的客户端软件为例,该配置文件为/opt/oracle/product/11.2.0/dbhome_1/network/admin/tnsnames.ora,默认文件内容为:
# tnsnames.ora Network Configuration File: /opt/oracle/product/11.2.0/dbhome_1/network/admin/tnsnames.ora # Generated by Oracle configuration tools. LISTENER_ORCL = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) )
可见在这里的客户端软件,ORCL是被指定为协议为TCP、IP地址为localhost,端口为1521的实例了,所以我们可以用sqlplus scott/123直接登录oracle。
客户端登录服务端
所以在只装oracle客户端的机器上,要使用sqlplus scott/123@orcl_133登录远程oracle的服务端,需要在该机器的tnsnames.ora文件增加:
ortcl_133 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.94.133)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)
初始化配置
- 对缺省密码的有效期进行修改
- 登录数据库
sqlplus /nolog
conn 账号/密码 as sysdba
,以管理员权限登录数据库
- 输入
alter profile default limit password_life_time unlimited;
- 登录数据库
- 对空表不备份进行修改(调整为全量备份)
- 输入
alter system set deferred_segment_creation=false;
- 输入
备份与导入
备份
https://blog.csdn.net/xuheng8600/article/details/84324707
导入
创建表空间和用户,以IDC_U_STUWORK为例
oracle命令行登录
sqlplus 用户名/密码
创建表空间IDC_U_STUWORK,指定存储文件及路径/u01/app/oracle/oradata/orcl/IDC_U_STUWORK.dbf,表空间大小360M
create tablespace IDC_U_STUWORK datafile '/u01/app/oracle/oradata/orcl/IDC_U_STUWORK.dbf' size 360M;
扩展:
- 删除表空间:
drop tablespace 表空间名
- 删除本地文件
/u01/app/oracle/oradata/orcl/IDC_U_STUWORK.dbf
即可
- 删除表空间:
创建用户并指定默认表空间
create user IDC_U_STUWORK identified by Jiaminjm1 default tablespace IDC_U_STUWORK;
赋予普通用户权限给用户
grant connect,resource to IDC_U_STUWORK;
DBA: 拥有全部特权,是系统最高权限,只有DBA才可以创建数据库结构。
RESOURCE:拥有Resource权限的用户只可以创建实体,不可以创建数据库结构。
CONNECT:拥有Connect权限的用户只可以登录Oracle,不可以创建实体,不可以创建数据库结构。
对于普通用户:授予connect, resource权限。
对于DBA管理用户:授予connect,resource, dba权限。切换用户
sqlplus IDC_U_STUWORK/Jiaminjm1
导入dmp数据
导入
# 三种方式 方式一: 1.将oracle_6.0.4.dmp文件上传到/u01/app/oracle/admin/orcl/dpdump/中 2. impdp IDC_U_STUWORK/Jiaminjm1@orcl file=oracle_6.0.4.dmp full=y ignore=y remap_schema=bladex_release:IDC_U_STUWORK transform=segment_attributes:n 方式二: 1.将oracle_6.0.4.dmp文件上传到/opt/dmp中 2.修改文件属组: chown -R oracle:oinstall /opt/dmp 3.创建文件夹dir:SQL> create directory dir as '/opt/dmp'; 4.授权用户访问授权:SQL> grant read,write on directory dir to IDC_U_STUWORK; 5. impdp idc_u_stuwork/Jiaminjm1@orcl directory=dir dumpfile=oracle_6.0.4.dmp remap_schema=bladex_release:IDC_U_STUWORK transform=segment_attributes:n
问题:ORA-39088: file name cannot contain a path specification
解决:方式一的错误,log文件名不能包含路径,直接修改成为文件名即可
问题:ORA-39145: directory object parameter must be specified and non-null
解决:方式一的错误,权限问题,给予用户最高权限
grant dba to 用户名
问题:导入时,出现大量ORA-39112: dependent object type comment skipped
解决:方式一的错误,没有指定用户转移,语句中增加参数
remap_schema=bladex_release:IDC_U_STUWORK transform=segment_attributes:n
扩展:
remap_schema=bladex_release:IDC_U_STUWORK 原来的schema:现在的schema
transform=segment_attributes:n 去掉表空间和存储子句
表空间、用户、权限
https://blog.csdn.net/wang_chaodong/article/details/116243090
使用sys账号进行操作
# 查看哪些用户拥有dba权限
select * from dba_role_privs where granted_role='DBA';
# 去掉权限
revoke dba from 用户名;
# 修改密码
alter user 用户(sys) identified by 密码;
# 授权
grant connect, resource to 用户名;
创建用户视图
向第三方提供视图,需要建个新用户(用户名2),并且只授权这一个视图的查询权限
创建用户
create user 用户名2 identified by 密码 default tablespace tbs1 temporary tablespace tbs1_temp profile DEFAULT;
授权(使用sys/system用户)
grant connect,resource to 用户名2; --这两个是普通用户必须要的两个权限 grant CREATE SYNONYM to 用户名2; --这个为了之后查询时方便,创建同义词权限 grant select on 用户名1.视图名 to 用户名2; --授权一张表/视图的查询权限
创建同义词(使用用户名2)
create synonym 视图名 for 用户名1.视图名;
查询即可
连接数查询
--查看当前连接数
select count(*) from v$session
--查看最大连接数
select value from v$parameter where name = 'processes'
查看连接数是否占满,对比上面两个查出来的数即可
plsql,sqlplus连接oracle非常慢,偶尔能连接上
原因是监听日志过大,4G封顶,一般windows装的oracle会出现此情况
解决:\app\Administrator\diag\tnslsnr\LS–20171012URU\listener\trace\listener.log,找到该路径,备份到其他地方后删除掉(需要先关闭监听服务TNSListner)。
Oracle密码过期, 报:ORA-01017: 用户名/口令无效; 登录被拒绝…
通过sys进入管理员
查询密码有效期时间
select * from dba_profiles where profile='DEFAULT' and resource_name='PASSWORD_LIFE_TIME'; 默认是180天,改成无限制 alter profile default limit password_life_time unlimited; 再查询一下,注意事务
修改新密码,不修改的话密码仍然是失效的
alter user 数据库用户名 identified by 数据库新密码;
Oracle把一个表的数据复制到另一个表中
1、新增一个表,通过另一个表的结构和数据: create table tab2 as select * from tab1; 2、如果表存在: insert into tab2 select * from tab1; 3、同一个表中,将A字段的值赋给B字段: update table_name set B = A; 4、将一个表的字段数据插入到另一个表的字段数据中 insert into tab2 (t_code, t_name) select pk_code, pk_name from tab1; * 如果报提醒:ORA-00928: 缺失 select 关键字错误。 原因是:这里tab1(Field1,Field2,....)不能加单引号 5. 多个表的多个字段,插入同一个表的多个字段。 insert into tab1 (tab_id, tab2_name, tab_code) select a.pk_id, b.pk_name, b.pk_code from tab1 a, tab2 b where a.pk_id = '7777' and b.pk_code = '12';
表空间占满
进入sys用户
查看表空间占用率
--因为表空间会涉及多个物理文件存储,此sql用于查看整个表空间的使用率(汇总版) SELECT a.tablespace_name , a.bytes / 1024 / 1024 大小M, b.bytes / 1024 / 1024 已使用M, c.bytes / 1024 / 1024 空余M, (b.bytes * 100) / a.bytes 使用率 FROM sys.sm$ts_avail a, sys.sm$ts_used b, sys.sm$ts_free c WHERE a.tablespace_name = b.tablespace_name AND a.tablespace_name = c.tablespace_name;
查看表空间物理文件占用率
--此sql拆解查看表空间中具体哪个物理文件占用高 SELECT D.TABLESPACE_NAME 表空间, D.FILE_NAME 物理文件名, D.AUTOEXTENSIBLE 是否开启自动扩展, ROUND(D.BYTES / 1024 / 1024,2) 已使用M, ROUND(D.MAXBYTES / 1024 / 1024,2) 总容量M, ROUND((D.BYTES * 100) / D.MAXBYTES,2) 文件使用率 FROM DBA_DATA_FILES D --WHERE D.TABLESPACE_NAME = 'SYSTEM';
找到对应占用高的物理文件扩容
方法一(将原物理文件扩展):
--物理文件不能超过32G alter database datafile '表空间位置' resize 新的尺寸 例如: alter database datafile '/ora_data/icsdb/system01.dbf' resize 500M;
方法二(增加物理文件个数):
alter tablespace 表空间名称 add datafile '新的数据文件地址' size 数据文件大小 例如: alter tablespace system add datafile '/ora_data/icsdb/system02.dbf' size 10G; --增加后需要方法三,开启自动扩展
方法三(设置表空间自动扩展):
alter database datafile '数据文件位置' autoextend on next 自动扩展大小 maxsize 最大扩展大小 例如: alter database datafile '/ora_data/icsdb/system02.dbf' autoextend on next 500m maxsize 31G;
扩展:
创建表空间
create tablespace 表空间名称 datafile 'c:\app\gen\oradata\myora\xxx.dbf' size 表空间初始大小100m autoextend on next 1024m maxsize 20480m;
删除表很大的日志文件,缩小表空间
查询表空间下的表占用大小
--查表空间内的表占用大小,用去缩小占用,大多数用来清除日志文件 select t.owner,t.segment_name,t.tablespace_name,bytes/1024/1024/1024 as sizes,q.num_rows,t.segment_type from dba_segments t left join dba_tables q on t.segment_name=q.table_name and t.owner=q.owner where t.segment_type='TABLE' and t.tablespace_name='TS_AAA' --需要查看的表空间 order by bytes/1024/1024/1024 desc
删除表数据
truncate或delete
Oracle数据表删除后,表空间没有减少,需要压缩空间
alter table 表1 enable row movement; alter table 表1 shrink space;
表数量统计
mysql:
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
oracle:
--统计当前用户表
SELECT COUNT(*) FROM USER_TABLES;
--统计所有用户表
SELECT COUNT(*) FROM all_tables;
日志清理
1、清理归档日志:ORA-00257:archiver error. Connect internal only. unitl freed.
查看《Oracle归档日志清理.md》
2、清理审计$AUD日志:磁盘满,system表空间满
https://www.php.cn/faq/489599.html
3、清理监听日志:磁盘满
linux:日志大小无限制
http://www.manongjc.com/detail/60-vzeflwcchtyefxv.html
windows:日志4G封顶
解决:\app\Administrator\diag\tnslsnr\LS–20171012URU\listener\trace\listener.log,找到该路径,备份到其他地方后删除掉(需要先关闭监听服务TNSListner)。
自动备份
数据库备份
本教程可使用 system 账户将整个实例备份(包含空表),并自动删除超过 6 天 的历史数据。
root 用户登录服务器
mkdir -p /backup/oracledata #新建 Oracle 数据库备份目录 chown -R oracle:oinstall /backup/oracledata #设置目录权限为 oinstall 用 户组的 oracle 用户(用户 oracle 与用户组 oinstall 是在安装 Oracle 数据库时 设置的)
创建目录对象
因为使用 expdp 命令需要使用到目录对象(directory),所以首先需要创建目 录对象,并赋予某个用户对目录对象的操作权限。
su – oracle #切换到 oracle 用户
sqlplus / as sysdba #切换到 SQLPLUS 环境
执行以下命令:
create directory expdp_bak_dir as '/backup/oracledata'; #指定输出目录
报错:
ERROR at line 1: ORA-01034: ORACLE not available
原因:一般是由于监听或Oracle没有启动
首先先测试一下,监听是否启动:lsnrctl status;如果监听没有启动,则 lsnrctl start;
启动oracle
sqlplus / as sysdba
startup
报错:LRM-00109: could not open parameter file ‘/u01/app/oracle/product/11.2.0.4/dbhome_1/dbs/initecard.ora’
原因:看到找不到intecard.ora。记得自己的实例创建时是orcl。有可能是因为变量设置出现问题。实例名ORACLE_SID设置不对
su - oracle
vim .bash_profile
- 修改ORACLE_SID=orcl
- 重启变量
source .bash_profile
- 再次尝试启动oracle
编辑自动备份脚本
vi /backup/oracledata/oradatabak.sh
#新建文件,输入以下代码#!/bin/sh export ORACLE_SID=orcl export ORACLE_HOME=/u01/app/oracle/product/11.2.0.4/dbhome_1 export NLS_LANG=american_america.al32utf8 export DATA_DIR=/backup/oracledata now=` date +%Y%m%d%H%M%S ` dmpfile=db$now.dmp echo start exp $dmpfile ... /u01/app/oracle/product/11.2.0.4/dbhome_1/bin/expdp system/password DUMPFILE=$dmpfile logfile=db$now.log DIRECTORY=expdp_bak_dir full=y echo "Delete the file bakup before 6 days..." find /backup/oracledata/ -mtime +6 -name "*.dmp" -exec rm -rf '{}' \; echo "Delete the file bakup successfully. " echo "Bakup completed."
注意点:
第二行ORACLE_SID,改为数据库的实例名
第九行,必须是目录后,空格,用户名/密码
不能将用户名密码一直到full=y另起一行写,会出错,因为这是一个完整的语句。
错误信息 /backup/oracledata/oradatabak.sh: line 10: system/password: No such file or directory
备份文件目录:/backup/oracledata
chmod +x /home/backup/oracledata/ordatabak.sh #添加脚本执行权限
设置系统自动定时执行备份脚本
vi /etc/crontab #编辑系统任务计划
将下面的代码写入最后一行:
0 0 * * * oracle /backup/oracledata/oradatabak.sh
./oradatabak.sh
是手动备份#每天凌晨 0 点 00 分,以 oracle 用户执行 oradatabak.sh 备份文件
[root@db ~]# systemctl restart crond.service
或service crond restart
[root@db ~]# systemctl enable crond.service
即每天凌晨 0 点 00 分进行备份,如需每天备份多次,可设置不同时间段备份:
例如:* 3,13,18 * * * oracle /backup/oracledata/oradatabak.sh 即每天 3 点、13 点、18 点进行备份。
说明:文件备份目录,用户oracle必须有更改权限,否则无法备份。
问题:到时间了却没有备份。查看当前时间
date
,发现系统时间不同步解决:
yum -y install ntpdate
ping baidu.com
,确定能访问外网/usr/sbin/ntpdate stdtime.gov.hk
同步时间date
查看时间
问题:时区有问题
解决:
https://blog.csdn.net/weixin_42167759/article/details/90648225
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
timedatectl set-timezone Asia/Shanghai
#其他时区以此类推如果是旧版(Cenos6及Ubuntu16以前版本)
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
数据库备份恢复
恢复需在数据库服务器上进行,并保持程序、数据文件路径与备份前一致。
在 PL/SQL 环境,设置数据库导入目录
SQL>create directory impdp_dir as '/backup/oracledata';
在 PL/SQL 环境,授权 SYSTEM 用户访问授权
SQL>grant read,write on directory impdp_dir to system;
在控制台环境,在系统目录中创建目录
mkdir -p /backup/oracledata
复制数据库备份文件至/backup/oracledata/目录
5)修改复制过来文件的权限
chown -R oracle:oinstall /backup/oracledata
- 在控制台环境,恢复数据库(全库恢复)
impdp system/kingstar@orcl DIRECTORY=EXPDP_BAK_DIR DUMPFILE= db20220104023001.dmp logfile= dmpfile.log full=y ignore=y
注意:
- logfile会在当前目录自动创建,不需要修改
问题:bash: Impdp: command not found…
解决:是因为没有切换用户,
su - oracle
,再次尝试
问题:oracle用户的权限不够
ORA-31640: unable to open dump file "/backup/oracledata/expdat.dmp" for read ORA-27041: unable to open file Linux-x86_64 Error: 13: Permission denied
解决:是因为复制过来的备份文件所有者是root,需要修改为oracle
chown -R oracle:oinstall /backup/oracledata
问题
plsql有表名,但select提示表不存在
解决:加双引号,
select * from "user"
原因:表名是小写的,通过
select * from user
查不到,oracle严格区分大小写,不加引号会默认变成大写。为什么有些表能查到呢,因为小写的表名在创建表语句时,
create table "user"
,导致固定了小写,我们只能用小写查。然而平时创建表时不加create table user
,这样创建出来的表就不区分大小写,因此我们可以不加引号随意查。oracle占用CPU100%
查看《oracle占用CPU100%.md》
SQL
oracle查询重复数据
1、查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断 select * from 表 where Id in (select Id from 表 group by Id having count(Id) > 1) 2、删除表中多余的重复记录,重复记录是根据单个字段(Id)来判断,只留有rowid最小的记录 DELETE from 表 WHERE (id) IN ( SELECT id FROM 表 GROUP BY id HAVING COUNT(id) > 1) AND ROWID NOT IN (SELECT MIN(ROWID) FROM 表 GROUP BY id HAVING COUNT(*) > 1); 3、查找表中多余的重复记录(多个字段) select * from 表 a where (a.Id,a.seq) in(select Id,seq from 表 group by Id,seq having count(*) > 1) 4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录 delete from 表 a where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)
一张表更新另一张表字段
UPDATE table1 t1 SET t1.column_to_update = (SELECT t2.column_to_copy FROM table2 t2 WHERE t1.join_column = t2.join_column); table1是要进行更新的表。 table2是提供字段值的表。 column_to_update是要更新的字段名。 column_to_copy是提供值的字段名。 join_column是用于连接两个表的列,通常是共有的某个关键列。
查询系统参数是否会立即生效
select name,value ,ISSYS_MODIFIABLE from v$parameter where name like '%名字%'; name value issys_mod sga_max_size 612368567 FALSE sga_target_size 612368567 immediate ISSYS_MODIFIABLE 返回是false 说明该参数无法用alter system语句动态修改,需要重启数据库。 其中issys_mod有三种状态:1.IMMEDIATE 立即生效 2. DEFERRED 只对后续的session生效 3.FLASE 必须重启生效
低版本客户端(plsql、navicat)连接高版本数据库报错
问题现象1:使用oracle 11.2.0.1 的客户端,对19c的服务端进行连接时,报错:ORA-28040: No matching authentication protocol 处理办法:在服务器端添加了允许登录的客户端版本 su - oracle vi $ORACLE_HOME/network/admin/sqlnet.ora 粘贴以下语句到文件里: SQLNET.ALLOWED_LOGON_VERSION_SERVER=11 SQLNET.ALLOWED_LOGON_VERSION_CLIENT=11 问题现象2:低版本客户端连接高版本数据库报错ORA-01017账号密码错误,能确定账号密码是对的就是登录不上去。 处理办法: 1、查询用户的PASSWORD_VERSIONS密码版本: SQL> select username, password_versions from dba_users where password_versions is not null; 2、修改密码 alter user 用户 identified by "密码"; 3、再次查询步骤1的密码版本,看是否有变化。再尝试登录