遇到這個錯誤,一般我們想到的是資料庫使用者被鎖,只需要執行使用者解鎖即可恢復,但這裡之所以寫出來是因為比較奇葩的一個問題。
昨天下午接同事資訊,說一個使用者連線報被鎖,經過溝通發現其實連線一個ADG的備庫作為只讀使用者查詢資料使用,於是按照他提供的相關資料庫伺服器資訊登入檢查,發現賬號居然沒有被鎖定,但通過其賬號密碼登入嘗試確實報ORA-28000: the account is locked,這就比較奇葩了,下面將處理過程做個記錄,希望對其他同仁有所借鑑。
一、錯誤現象
SQL> conn dbuser/dbuser; ERROR: ORA-28000: the account is locked
二、錯誤原因
使用者通過錯誤密碼登入,超出失敗登入限制,導致使用者被鎖。
三、處理過程
1.登入備庫,檢視資料庫使用者字典
賬號處於open狀態,為何使用者會被鎖呢?登入主庫檢視發現賬戶依舊正常,但通過使用者名稱密碼登入沒有被鎖的資訊
這就奇怪了,使用者沒有被鎖,主庫可以登入,為何備庫就顯示被鎖呢?難道是備庫的多次登入失敗導致使用者被鎖,因為備庫只讀導致資料字典記錄不到鎖定資訊?
經過測試發現確實是在備庫通過錯誤的使用者密碼登入,會導致備庫的賬號被鎖定,但在字典不會記錄賬戶被鎖資訊,同時主庫可以正常登入。
登入統計
select name,LCOUNT from user$ where name='DBUSER';
2.備庫使用者解鎖
alter user dbuser account unlock;
再次登入,可以登入。但稍等幾分鐘後重試,依舊提示被鎖。
3.嘗試重啟資料庫恢復
重啟後使用者恢復正常,但等一會後又提示使用者被鎖定。
4.放大招,更改使用者profile,使登入失敗無限制
檢視使用者對應的profile做的密碼、登入限制
set line 200;
set pagesize 2000;
col resource_name for a30;
col profile for a18;
col limit for a15;
select a.username,a.profile,b.resource_name,b.limit from dba_users a,dba_profiles b where a.profile=b.profile and b.resource_name='FAILED_LOGIN_ATTEMPTS' and a.username='APP_BG';
更改使用者登入限制
SQL> alter profile default limit FAILED_LOGIN_ATTEMPTS UNLIMITED; Profile altered.
5.問題追蹤
究竟是哪個IP一直嘗試使用不正確的密碼登入資料庫呢?我們可以通過幾種方法去traceroute,可以通過登入審計的方式(由於是備庫,所以需要開啟系統級別的審計),可以通過tcpdump抓包的形式分析連線資料庫的資訊。這裡做的是資料庫審計的方式完成問題追蹤,具體方法如下:
1)確定使用者狀態
select username, ACCOUNT_STATUS ,LOCK_DATE ,expiry_date from dba_users order by lock_date desc ;
2)檢視審計資訊
show parameter audit;
audit_sys_operations boolean FALSE
audit_syslog_level string
audit_trail string NONE
發現審計未開啟
開啟資料庫審計
alter system set audit_sys_operations=TRUE scope=spfile; --審計管理賬戶,一般設定false alter system set audit_trail=os,extended scope=spfile; 重啟資料庫
3)跟蹤審計日誌
show parameter audit_file_dest
4)分析審計日誌連線的使用者、IP地址等
若使用的是DB級別的審計,可通過下面的語句檢視登入審計資訊
SELECT username,TIMESTAMP,os_username,userhost, OS_PROCESS,RETURNCODE FROM sys.dba_audit_session WHERE returncode != 0 AND TIMESTAMP>='2015-12-09 13:25:00' ;
四、附錄
1.參考文件
有篇文章說是mos上的一篇說了這個問題是由於主庫(經過測試,發現此描述有問題,請忽略)
ORA-28000 On Active Data Guard (文件 ID 1922621.1) In this Document Symptoms Cause Solution References APPLIES TO: Oracle Database - Enterprise Edition - Version 11.2.0.1 and later Information in this document applies to any platform. SYMPTOMS Noticed one user account was locked in primary and its Active Data Guard instances. It was fine Primary Database after unlocking the User, but at the Active Data Guard Standby Database, it was showing ORA-28000 that the account is still locked. Followed Note 1600401.1: ORA-28000 "the account is locked" in the standby database, even after the account was unlocked in the primary but it is still unlocked and user can not connect to standby database. Here is log:
2.資料庫審計
Audit_trail:
None:是預設值,不做審計;
DB:將audit trail 記錄在資料庫的審計相關表中,如aud$,審計的結果只有連線資訊;
DB,Extended:這樣審計結果裡面除了連線資訊還包含了當時執行的具體語句;
OS:將audit trail 記錄在作業系統檔案中,檔名由audit_file_dest引數指定;
xml:10g裡新增的。
注:這兩個引數是static引數,需要重新啟動資料庫才能生效。
當開啟審計功能後,可在三個級別對資料庫進行審計:Statement(語句)、PRivilege(許可權)、object(物件)。
(1) 語句審計 AUDIT SELECT TABLE BY username ; AUDIT SESSION BY jeff, lori; (2) 許可權審計 AUDIT DELETE ANY TABLE BY ACCESS WHENEVER NOT SUCCESSFUL; AUDIT DELETE ANY TABLE; AUDIT SELECT TABLE, INSERT TABLE, DELETE TABLE, EXECUTE PROCEDURE BY ACCESS WHENEVER NOT SUCCESSFUL; (3) 物件審計 AUDIT DELETE ON jeff.emp; AUDIT SELECT, INSERT, DELETE ON jward.dept BY ACCESS WHENEVER SUCCESSFUL; (4) 取消審計 NOAUDIT session; NOAUDIT session BY jeff, lori; NOAUDIT DELETE ANY TABLE; NOAUDIT SELECT TABLE, INSERT TABLE, DELETE TABLE,EXECUTE PROCEDURE; NOAUDIT ALL; -- 取消所有statement審計 NOAUDIT ALL PRIVILEGES; -- 取消所有許可權審計 NOAUDIT ALL ON DEFAULT; -- 取消所有物件審計 (5) 清除審計 DELETE FROM SYS.AUD$; DELETE FROM SYS.AUD$ WHERE obj$name='EMP'; (6) 審計檢視 USER_AUDIT_STATEMENT -- 語句審計 USER_AUDIT_SESSION -- session審計 USER_AUDIT_OBJECT -- 審計物件列表 USER_AUDIT_TRAIL -- 審計記錄 (7) 將審計結果表從system表空間裡移動到別的表空間上 實際上sys.aud$表上包含了兩個lob欄位,並不是簡單的move table就可以。 下面是具體的過程: alter table sys.aud$ move tablespace users; alter table sys.aud$ move lob(sqlbind) store as( tablespace USERS); alter table sys.aud$ move lob(SQLTEXT) store as( tablespace USERS); alter index sys.I_AUD1 rebuild tablespace u ;