最新的項目開始使用Oracle後,5個月之間遇到一些在SqlServer中沒有遇到的問題,這裏記錄並貼上一些經常使用的解決辦法。html
剛開始咱們一直使用Oracle12C進行開發,到上線服務器時說12C與可能不太穩定,有些問題很差定位就轉用11g,這裏牽扯到12C導出的DMP文件導入到11G上的問題,導出導入語句:sql
exp 帳號/密碼@STO_DataBase file=D:\STO_DataBase.dmp full=y imp 帳號/密碼@STO_DataBase file=D:\DataBackUp\STO_DataBase.dmp full=y
導入報異常版本不同,沒法導入,這裏用一款小工具能夠解決問題下載地址。數據庫
數據庫文件大小受DB_BLOCK_SIZE決定,默認是8K對應的數據庫文件是32G,因此建立數據庫時數據庫的大小不要設置最大值最好設置成無限大,能夠多設置幾個數據庫文件,以避免數據庫大小不夠用引發數據庫異常。建立語句:c#
//建立表空間 CREATE TABLESPACE STO_Data LOGGING DATAFILE 'D:\DataBase\DbFile\STO_DATA.DBF', 'D:\DataBase\DbFile\STO_DATA1.DBF', 'D:\DataBase\DbFile\STO_DATA2.DBF' SIZE 512M AUTOEXTEND ON NEXT 512M MAXSIZE unlimited EXTENT MANAGEMENT LOCAL; //建立臨時表空間 CREATE TEMPORARY TABLESPACE STO_Temp TEMPFILE 'D:\DataBase\DbFile\STO_Temp.DBF' SIZE 512M AUTOEXTEND ON NEXT 512M MAXSIZE unlimite EXTENT MANAGEMENT LOCAL; //建立用戶 CREATE USER 用戶名 IDENTIFIED BY 用戶名密碼 DEFAULT TABLESPACE STO_Data TEMPORARY TABLESPACE STO_Temp //用戶賦權限 grant connect,resource,dba to 用戶名
存儲過程的參數命名最好能夠按照規則來不然會有問題,例如:服務器
create or replace procedure Proc_Test(IN_CompanyName in varchar2, OUT_Table out sys_refcursor) as begin open OUT_Table for select * from Waybill_Pickup t where t.companyname=IN_CompanyName; end Proc_Test;
若是參數使用的和數據庫中的表字段同樣會引發失效,例如:oracle
create or replace procedure Proc_Test(CompanyName in varchar2, OUT_Table out sys_refcursor) as begin open OUT_Table for select * from Waybill_Pickup t where t.companyname=CompanyName; end Proc_Test;
長時間使用會使Temp文件愈來愈大,而引發某些操做異常。app
alter tablespace STO_TEMP shrink space;
Oracle批量插入若是是用Oracle.DataAccess.Client.OracleBulkCopy 類,數據在插入過程當中會引發索引失效,若是是業務表就會引發業務查詢很是緩慢。可是插入效率很高,若是數據庫使用讀寫分離,或者接口採用讀寫分離的兩個表能夠經過此方法進行插入,若是遇到索引失效可用如下語句查看和修復。工具
//查看失效索引 select * from user_indexes where Status='UNUSABLE' //重建失效索引 begin FOR cur in (select INDEX_NAME from user_indexes where Status='UNUSABLE') loop execute immediate 'alter index '|| cur.INDEX_NAME||' rebuild' ; END LOOP; end;
當Oracle遇到內部問題出現異常和掛機後的排查步驟(Oracle服務器)oop
參考文檔ui
當時遇到的問題是:數據庫直接Down掉了,鏈接時報沒有監聽程序。重啓服務器後過一會數據庫就掛掉了
檢查Oracle日誌:
D:\app\Administrator\diag\rdbms\sto_database\stodatabase\alert
查看Log文件,在日誌文件中找到錯誤信息提示:
檢查跟蹤文件
D:\app\Administrator\diag\rdbms\sto_database\stodatabase\trace
在跟蹤文件中查看錯誤信息引發的緣由:
根據錯誤查找出引發錯誤的SQL語句,最後定位到是單條語句超過65535個參數引發,因爲.net中使用了DbDataAdapter進行保存數據,他相似於拼接的Sql語句,更改批次提交數解決問題。
DbCommand處理Oracle數據庫默認參數綁定是按次序且不能查詢LONG RAW類型,處理SqlServer數據庫不用處理,
因此在初始化DbCommand時須要加入以下代碼
(cmd as Oracle.DataAccess.Client.OracleCommand).BindByName=true; (cmd as Oracle.DataAccess.Client.OracleCommand).InitialLONGFetchSize = -1;
OracleBulkCopy在Oracle.DataAccess.DLL中,速率很快,但不進行主鍵和惟一鍵檢查,常常會將惟一索引弄壞,而且在插入過程當中普通索引也會失效。
/// <summary> /// 批量插入數據庫 /// </summary> /// <param name="datatable"></param> /// <returns></returns> public string OracleBulkInsert(DataTable datatable) { OracleBulkCopy bulkCopy = new OracleBulkCopy(_connStr, OracleBulkCopyOptions.UseInternalTransaction); try { bulkCopy.DestinationTableName = datatable.TableName; bulkCopy.BulkCopyTimeout = 600000; bulkCopy.BatchSize = 50000; if (datatable != null && datatable.Rows.Count != 0) bulkCopy.WriteToServer(datatable); return ""; } catch (Exception ex) { throw ex; } finally { if (bulkCopy != null) bulkCopy.Close(); } }
DataTable在插入時應注意字段類型和順序,能夠用如下代碼得到表結構
/// <summary> /// 根據表名獲取Table結構 /// </summary> /// <param name="tableName">表名</param> /// <returns></returns> public DataTable InitStructureByTable(string tableName) { DataTable dtColums = helper.GetDataSet("select column_name,data_type from user_tab_columns where table_name='" + tableName.ToUpper() + "' order by column_id", null).Tables[0]; DataTable dtNew = new DataTable(); dtNew.TableName = tableName; //匹配列數 for (int j = 0; j < dtColums.Rows.Count; j++) { switch (dtColums.Rows[j][1].ToString().ToUpper()) { case "DATE": dtNew.Columns.Add(new DataColumn(dtColums.Rows[j][0].ToString(), typeof(DateTime))); break; case "NUMBER": dtNew.Columns.Add(new DataColumn(dtColums.Rows[j][0].ToString(), typeof(double))); break; default: dtNew.Columns.Add(new DataColumn(dtColums.Rows[j][0].ToString(), typeof(string))); break; } } return dtNew; }
這種插入方式要比OracleBulkCopy要慢,至關於拼接了帶參數的插入語句插入,注意UpdateBatchSize數值不要過大,不然可能因爲單句Sql語句參數超過65535引發數據庫崩潰。
/// <summary> /// 批量插入數據庫 /// </summary> /// <param name="datatable"></param> /// <returns></returns> public string BulkInsertCopy(DataTable datatable) { DbDataAdapter adapter = _factory.CreateDataAdapter(); DbCommand cmd = _factory.CreateCommand(); DbCommandBuilder cb = _factory.CreateCommandBuilder(); try { adapter.UpdateBatchSize = 200; using (DbConnection conn = _factory.CreateConnection()) { conn.ConnectionString = ConnectionString; conn.Open(); cmd.Connection = conn; //cmd.Transaction = conn.BeginTransaction(); cb.DataAdapter = adapter; adapter.SelectCommand = cmd; adapter.SelectCommand.CommandText = "select * from " + datatable.TableName; adapter.FillSchema(datatable, SchemaType.Source); adapter.Update(datatable); //cmd.Transaction.Commit(); } return ""; } catch (Exception ex) { //cmd.Transaction.Rollback(); return ex.Message; } finally { cmd.Dispose(); cb.Dispose(); adapter.Dispose(); } }