夢(mèng)數(shù)據(jù)庫(kù)實(shí)戰(zhàn):從安裝部署到數(shù)據(jù)遷移的踩坑全記錄)
國(guó)產(chǎn)數(shù)據(jù)庫(kù)這幾年確實(shí)是技術(shù)圈繞不開的話題尤其是隨著行業(yè)對(duì)自主可控的要求越來(lái)越高國(guó)產(chǎn)數(shù)據(jù)庫(kù)從“能用”到“好用”的轉(zhuǎn)變非常明顯。我最近剛學(xué)完《國(guó)產(chǎn)數(shù)據(jù)庫(kù)技術(shù)》這門課課程里花了大量時(shí)間在達(dá)夢(mèng)數(shù)據(jù)庫(kù)DM數(shù)據(jù)庫(kù)的實(shí)踐上。說(shuō)實(shí)話沒(méi)動(dòng)手之前我以為這就是個(gè)“換皮Oracle”真正用下來(lái)才發(fā)現(xiàn)它確實(shí)在兼容上下足了功夫但也有很多自己的脾氣和邏輯。這篇就把我這段時(shí)間從安裝部署到實(shí)操踩坑的心得整理一下給正在學(xué)或者準(zhǔn)備上手DM數(shù)據(jù)庫(kù)的朋友做個(gè)參考。1. 達(dá)夢(mèng)數(shù)據(jù)庫(kù)整體認(rèn)知它到底是個(gè)什么定位1.1 國(guó)產(chǎn)數(shù)據(jù)庫(kù)賽道里的位置國(guó)產(chǎn)數(shù)據(jù)庫(kù)現(xiàn)在大體分幾派有從開源生態(tài)發(fā)展起來(lái)的比如基于PostgreSQL、MySQL內(nèi)核二次開發(fā)的也有完全自主研發(fā)的。達(dá)夢(mèng)屬于后者它走的是“自主研發(fā)高度兼容Oracle”的路線。這個(gè)定位很聰明因?yàn)閲?guó)內(nèi)大量企業(yè)級(jí)系統(tǒng)以前跑在Oracle上數(shù)據(jù)庫(kù)管理員和開發(fā)者的思維習(xí)慣都是Oracle那套如果能做到“上手即用”遷移成本就低很多。我在課程里第一次接觸DM8的時(shí)候第一感覺(jué)就是命令行工具叫disqlSQL語(yǔ)法風(fēng)格、數(shù)據(jù)字典視圖比如DBA_TABLES、DBA_VIEWS、PL/SQL寫法都帶著濃厚的Oracle影子。但深入用下來(lái)你會(huì)發(fā)現(xiàn)在某些細(xì)節(jié)上它并不是完全照搬比如它的存儲(chǔ)結(jié)構(gòu)、表空間管理模式、備份恢復(fù)機(jī)制都有自己的一套設(shè)計(jì)邏輯。1.2 DM數(shù)據(jù)庫(kù)的架構(gòu)特點(diǎn)達(dá)夢(mèng)的體系架構(gòu)大體還是“實(shí)例數(shù)據(jù)庫(kù)”的模式一個(gè)實(shí)例對(duì)應(yīng)一個(gè)數(shù)據(jù)庫(kù)實(shí)例由內(nèi)存結(jié)構(gòu)和后臺(tái)進(jìn)程組成。內(nèi)存結(jié)構(gòu)里比較核心的是緩沖池Buffer Pool、日志緩沖區(qū)Log Buffer、字典緩存等這些概念如果你熟悉Oracle就一點(diǎn)都不陌生。一個(gè)值得單獨(dú)說(shuō)的點(diǎn)是DM8的“模式Schema”和“用戶”的關(guān)系。在達(dá)夢(mèng)里創(chuàng)建一個(gè)用戶時(shí)會(huì)自動(dòng)創(chuàng)建一個(gè)同名的模式用戶在默認(rèn)模式下創(chuàng)建的表、視圖都?xì)w屬到這個(gè)模式。這一點(diǎn)和Oracle的行為一致但對(duì)于習(xí)慣MySQL里“庫(kù)”和“用戶”完全獨(dú)立的人來(lái)說(shuō)需要轉(zhuǎn)換一下思路。這里有個(gè)實(shí)操中的小體會(huì)達(dá)夢(mèng)的sysdba賬號(hào)類似于Oracle的sys擁有最高權(quán)限日常開發(fā)盡量不要用它去連業(yè)務(wù)庫(kù)建議單獨(dú)建業(yè)務(wù)賬號(hào)并授予必要的權(quán)限。我在做練習(xí)時(shí)一開始圖省事全程用sysdba結(jié)果后面想測(cè)試權(quán)限控制相關(guān)的功能時(shí)還得回頭重新建用戶和授權(quán)增加了不少工作量。1.3 兼容性策略兼容但不等于替代課程里有一句話我印象很深達(dá)夢(mèng)追求的是“兼容”而非“替代”。也就是說(shuō)它努力做到讓原來(lái)跑在Oracle上的應(yīng)用能平滑遷移過(guò)來(lái)但不是所有Oracle高級(jí)特性都能直接一一對(duì)應(yīng)。舉個(gè)例子Oracle里有物化視圖達(dá)夢(mèng)8也支持Oracle有自治事務(wù)PRAGMA AUTONOMOUS_TRANSACTION達(dá)夢(mèng)也有類似的實(shí)現(xiàn)。但有些冷門的內(nèi)置函數(shù)、特定的包Package行為可能就需要手動(dòng)調(diào)整。所以做遷移評(píng)估的時(shí)候不能只看業(yè)務(wù)能不能跑起來(lái)還要注意跑起來(lái)之后的性能是否達(dá)標(biāo)、是否有隱藏的兼容性坑。我在課程實(shí)驗(yàn)里用達(dá)夢(mèng)自帶的遷移工具把一套模擬的學(xué)生選課系統(tǒng)從Oracle遷移到DM8表面上所有表結(jié)構(gòu)和數(shù)據(jù)都遷過(guò)來(lái)了但實(shí)際跑存儲(chǔ)過(guò)程的時(shí)候報(bào)了好幾個(gè)錯(cuò)誤都是因?yàn)槟承㎡racle特有的寫法和內(nèi)置函數(shù)在達(dá)夢(mèng)里沒(méi)有完全等價(jià)物。這也算是給所有做國(guó)產(chǎn)化遷移的人提個(gè)醒遷移工具能幫你搬運(yùn)數(shù)據(jù)但代碼層面的適配工作一點(diǎn)都不能偷懶。2. 安裝部署實(shí)踐從零到能連上數(shù)據(jù)庫(kù)2.1 環(huán)境準(zhǔn)備與安裝包選擇達(dá)夢(mèng)數(shù)據(jù)庫(kù)有企業(yè)版、標(biāo)準(zhǔn)版還有一個(gè)開發(fā)版?zhèn)€人學(xué)習(xí)用。課程里用的是開發(fā)版功能和標(biāo)準(zhǔn)版基本一致只是授權(quán)和性能上有限制。下載安裝包之后解壓出來(lái)是一堆rpm包和腳本這和Oracle那種巨型安裝向?qū)耆煌?。我建議安裝的時(shí)候注意幾點(diǎn)用專門的用戶比如dmdba來(lái)安裝不要用root直接裝這是個(gè)好習(xí)慣可以避免權(quán)限混亂也符合生產(chǎn)環(huán)境的規(guī)范。安裝路徑規(guī)劃好不建議裝到系統(tǒng)盤根目錄因?yàn)閿?shù)據(jù)庫(kù)的數(shù)據(jù)文件會(huì)越來(lái)越大。disql這個(gè)命令行工具默認(rèn)字符集可能和你的終端不一致中文顯示亂碼的話需要調(diào)整NLS_LANG相關(guān)的環(huán)境變量。有個(gè)同學(xué)在安裝時(shí)沒(méi)注意磁盤空間數(shù)據(jù)目錄放到了根分區(qū)結(jié)果初始化實(shí)例到一半就報(bào)“磁盤空間不足”。這個(gè)看起來(lái)是很低級(jí)的錯(cuò)誤但實(shí)際操作里確實(shí)不少人會(huì)踩到尤其是用虛擬機(jī)裝的時(shí)候默認(rèn)分配的磁盤往往剛夠系統(tǒng)用根本沒(méi)有冗余給數(shù)據(jù)庫(kù)。2.2 初始化實(shí)例的“坑”安裝完數(shù)據(jù)庫(kù)軟件之后還需要初始化實(shí)例。達(dá)夢(mèng)初始化實(shí)例的工具叫dminit它會(huì)在指定目錄下生成數(shù)據(jù)文件、控制文件、日志文件等然后才能啟動(dòng)數(shù)據(jù)庫(kù)服務(wù)。初始化實(shí)例時(shí)幾個(gè)關(guān)鍵參數(shù)要特別留意PAGE_SIZE頁(yè)大小默認(rèn)是8K如果業(yè)務(wù)里有大數(shù)據(jù)量的行可能需要設(shè)成16K或32K。這個(gè)參數(shù)一旦初始化后就不能改了必須提前想清楚。CHARSET字符集默認(rèn)是GB18030如果你的應(yīng)用主要是UTF-8建議在初始化時(shí)就指定為UTF-8。我自己第一次就沒(méi)改后來(lái)為了調(diào)整這個(gè)參數(shù)折騰了很久。CASE_SENSITIVE大小寫敏感這個(gè)參數(shù)決定了標(biāo)識(shí)符大小寫是否敏感。默認(rèn)是敏感意味著你建表時(shí)寫CREATE TABLE Test和CREATE TABLE test產(chǎn)生的是不同的表。對(duì)于從Oracle遷移過(guò)來(lái)的應(yīng)用來(lái)說(shuō)保持默認(rèn)就好但如果你更習(xí)慣MySQL那種大小寫不敏感的方式這個(gè)參數(shù)要提前改。我在初始化的時(shí)候周圍好幾個(gè)同學(xué)都遇到一個(gè)情況實(shí)例初始化成功了但用disql連接時(shí)報(bào)“登錄密碼錯(cuò)誤”。后來(lái)發(fā)現(xiàn)是初始化時(shí)設(shè)置的密碼里包含了特殊字符而終端環(huán)境的轉(zhuǎn)義把密碼搞變了。解決方法是初始化時(shí)暫時(shí)用簡(jiǎn)單密碼等確認(rèn)能登錄后再用ALTER USER改成復(fù)雜密碼。2.3 啟動(dòng)與連接檢查實(shí)例初始化完成后啟動(dòng)服務(wù)有兩種方式一種是注冊(cè)成系統(tǒng)服務(wù)用systemctl管理另一種是直接用dmserver命令前臺(tái)啟動(dòng)適合調(diào)試場(chǎng)景。我建議學(xué)習(xí)階段用前臺(tái)方式啟動(dòng)因?yàn)橐坏?shù)據(jù)庫(kù)啟動(dòng)報(bào)錯(cuò)前臺(tái)模式可以立刻看到日志輸出方便定位問(wèn)題。跑生產(chǎn)的話當(dāng)然要注冊(cè)成服務(wù)并且設(shè)置開機(jī)自啟還要配置好自動(dòng)重啟策略。連接測(cè)試這一關(guān)除了用disql達(dá)夢(mèng)還提供了圖形化管理工具DM管理工具DM Management Tools。這個(gè)工具類似Oracle的SQL Developer可以圖形化地管理用戶、表空間、表結(jié)構(gòu)、執(zhí)行SQL腳本等。圖形化工具對(duì)于初學(xué)者很友好至少比在命令行里懵著敲命令強(qiáng)但實(shí)際工作中很多DBA還是習(xí)慣寫腳本畢竟批量操作的時(shí)候腳本效率高得多。有一個(gè)細(xì)節(jié)值得提一下達(dá)夢(mèng)默認(rèn)端口號(hào)是5236注意防火墻要放行否則遠(yuǎn)程連接不上。我課程實(shí)踐里出現(xiàn)過(guò)自己本機(jī)可以連、但從另外一臺(tái)虛擬機(jī)連不上的情況排查了半天最后發(fā)現(xiàn)就是虛擬機(jī)的防火墻擋了5236端口。3. 核心功能實(shí)踐建庫(kù)建表到數(shù)據(jù)處理3.1 創(chuàng)建表空間和用戶達(dá)夢(mèng)里創(chuàng)建表空間和用戶的順序和Oracle一致先建表空間再建用戶并指定用戶默認(rèn)表空間。這里面有個(gè)關(guān)聯(lián)邏輯表空間是存儲(chǔ)數(shù)據(jù)的物理容器而用戶模式是邏輯對(duì)象歸屬。實(shí)操里的標(biāo)準(zhǔn)流程大概是-- 創(chuàng)建表空間 CREATE TABLESPACE app_data DATAFILE /dm/data/DMDB/app_data.dbf SIZE 256M AUTOEXTEND ON NEXT 16M MAXSIZE 4G; -- 創(chuàng)建用戶并指定默認(rèn)表空間 CREATE USER app_user IDENTIFIED BY your_password DEFAULT TABLESPACE app_data; -- 授予基本權(quán)限 GRANT DBA TO app_user;這里要特別說(shuō)明一下GRANT DBA TO app_user在學(xué)習(xí)環(huán)境里這么干圖省事沒(méi)問(wèn)題但在生產(chǎn)環(huán)境絕對(duì)不能這樣做。DBA角色權(quán)限太大了等于把整個(gè)數(shù)據(jù)庫(kù)的鑰匙都給了業(yè)務(wù)賬號(hào)。正確做法是按需授權(quán)只授予業(yè)務(wù)實(shí)際需要的權(quán)限比如CREATE SESSION、CREATE TABLE、SELECT等。建表時(shí)達(dá)夢(mèng)的數(shù)據(jù)類型和Oracle高度一致包括NUMBER、VARCHAR2、DATE、CLOB、BLOB等這讓我從Oracle切過(guò)來(lái)的時(shí)候幾乎沒(méi)有學(xué)習(xí)成本。但如果你是從MySQL過(guò)來(lái)的可能會(huì)覺(jué)得NUMBER用起來(lái)不如INT直觀其實(shí)本質(zhì)上是一個(gè)東西就是定義方式不一樣。3.2 SQL兼容性常用語(yǔ)句的差異體驗(yàn)我在實(shí)踐里建了一個(gè)課程項(xiàng)目用的選課系統(tǒng)庫(kù)里面包含了學(xué)生表、課程表、選課記錄表還寫了幾個(gè)統(tǒng)計(jì)查詢。達(dá)夢(mèng)對(duì)標(biāo)準(zhǔn)SQL的支持很完整基本的JOIN、子查詢、聚合函數(shù)、排序、分頁(yè)都能用。有個(gè)分頁(yè)查詢的小差異特別值得注意。Oracle經(jīng)典的分頁(yè)寫法是ROWNUMMySQL是LIMIT而達(dá)夢(mèng)8直接支持LIMIT關(guān)鍵字同時(shí)也支持Oracle的ROWNUM。這意味著你可以用兩種方式寫分頁(yè)非常靈活。但需要提醒的是LIMIT在達(dá)夢(mèng)里不是所有場(chǎng)景都支持比如在某些子查詢或視圖定義里用LIMIT就可能報(bào)錯(cuò)這時(shí)候就要退回ROWNUM寫法。再比如空值處理達(dá)夢(mèng)默認(rèn)行為和Oracle一樣是“NULL不參與比較”這一點(diǎn)和MySQL的默認(rèn)行為不同。如果你之前寫慣了MySQL的查詢?cè)谶_(dá)夢(mèng)里遇到數(shù)據(jù)查不出來(lái)先別急著懷疑SQL寫錯(cuò)了很有可能是NULL處理邏輯不一樣。還有一個(gè)實(shí)用小技巧達(dá)夢(mèng)支持Dual表查詢SELECT SYSDATE FROM DUAL;這個(gè)Oracle特性被完整保留了下來(lái)。3.3 存儲(chǔ)過(guò)程和觸發(fā)器PL/SQL風(fēng)格的延續(xù)達(dá)夢(mèng)的存儲(chǔ)過(guò)程語(yǔ)法和Oracle的PL/SQL非常接近支持DECLARE、BEGIN、EXCEPTION、游標(biāo)、存儲(chǔ)函數(shù)、觸發(fā)器等。課程里要求我們用存儲(chǔ)過(guò)程實(shí)現(xiàn)一個(gè)簡(jiǎn)單的選課事務(wù)邏輯判斷課程容量如果沒(méi)滿就插入選課記錄并更新已選人數(shù)滿了就拋出異常。我貼一段當(dāng)時(shí)寫的簡(jiǎn)潔版存儲(chǔ)過(guò)程供大家感受語(yǔ)法風(fēng)格CREATE OR REPLACE PROCEDURE sp_select_course( p_student_id IN VARCHAR2, p_course_id IN VARCHAR2 ) AS v_capacity NUMBER; v_selected NUMBER; BEGIN -- 查詢課程容量和已選人數(shù) SELECT capacity INTO v_capacity FROM course WHERE course_id p_course_id; SELECT selected_count INTO v_selected FROM course WHERE course_id p_course_id; IF v_selected v_capacity THEN RAISE_APPLICATION_ERROR(-20001, 課程容量已滿); END IF; -- 插入選課記錄更新已選人數(shù) INSERT INTO enroll_record(student_id, course_id) VALUES (p_student_id, p_course_id); UPDATE course SET selected_count selected_count 1 WHERE course_id p_course_id; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END;這個(gè)寫法如果之前寫過(guò)Oracle的PL/SQL基本可以直接跑兼容度確實(shí)很高。但我在實(shí)際測(cè)試?yán)锇l(fā)現(xiàn)達(dá)夢(mèng)對(duì)RAISE_APPLICATION_ERROR的參數(shù)類型要求比較嚴(yán)格如果傳進(jìn)去的字符串長(zhǎng)度超出限制會(huì)報(bào)錯(cuò)寫代碼時(shí)要注意控制錯(cuò)誤提示信息的長(zhǎng)度。觸發(fā)器方面達(dá)夢(mèng)支持BEFORE、AFTER、INSTEAD OF等類型語(yǔ)法和Oracle也基本一致。另一個(gè)細(xì)節(jié)是達(dá)夢(mèng)的自治事務(wù)用PRAGMA AUTONOMOUS_TRANSACTION聲明用于在觸發(fā)器里寫日志而不影響主事務(wù)的回滾。這和Oracle完全一樣在實(shí)際項(xiàng)目里非常好用。3.4 視圖與索引實(shí)踐視圖在達(dá)夢(mèng)里用起來(lái)和Oracle一樣支持創(chuàng)建普通視圖和物化視圖。我建了一個(gè)統(tǒng)計(jì)視圖用于課程選課人數(shù)統(tǒng)計(jì)語(yǔ)句大致如下CREATE OR REPLACE VIEW v_course_stats AS SELECT c.course_id, c.course_name, COUNT(e.student_id) AS enroll_cnt FROM course c LEFT JOIN enroll_record e ON c.course_id e.course_id GROUP BY c.course_id, c.course_name;索引方面達(dá)夢(mèng)支持B樹索引、位圖索引、全文索引等。在課程實(shí)踐里我給選課記錄表的student_id和course_id分別建了索引查詢性能提升還是很明顯的。經(jīng)驗(yàn)是索引不是越多越好每個(gè)索引在加快查詢的同時(shí)都會(huì)拖慢寫入速度并且占用存儲(chǔ)空間。要針對(duì)實(shí)際查詢模式來(lái)設(shè)計(jì)索引用EXPLAIN看執(zhí)行計(jì)劃是最靠譜的判斷方式。擴(kuò)展一個(gè)實(shí)踐心得達(dá)夢(mèng)可以通過(guò)在SQL前面加EXPLAIN關(guān)鍵字來(lái)查看執(zhí)行計(jì)劃這一點(diǎn)和Oracle一致。執(zhí)行計(jì)劃能清楚地告訴你SQL有沒(méi)有走索引、有沒(méi)有做全表掃描是排查性能問(wèn)題的最基本工具。我在調(diào)優(yōu)一個(gè)選課統(tǒng)計(jì)查詢時(shí)就是通過(guò)執(zhí)行計(jì)劃發(fā)現(xiàn)表連接順序不對(duì)調(diào)整了驅(qū)動(dòng)表和被驅(qū)動(dòng)表的順序后查詢時(shí)間從十幾秒降到了幾百毫秒。4. 數(shù)據(jù)管理實(shí)操備份恢復(fù)與遷移4.1 備份機(jī)制的理解與操作達(dá)夢(mèng)的備份分為物理備份和邏輯備份。物理備份備份的是數(shù)據(jù)文件本身恢復(fù)時(shí)能把數(shù)據(jù)庫(kù)恢復(fù)到備份時(shí)刻的狀態(tài)適合災(zāi)難恢復(fù)邏輯備份導(dǎo)出的是一系列SQL語(yǔ)句或記錄適合數(shù)據(jù)遷移、異構(gòu)數(shù)據(jù)庫(kù)之間交換數(shù)據(jù)。我在實(shí)踐中重點(diǎn)測(cè)試了物理備份和恢復(fù)達(dá)夢(mèng)也有類似Oracle的歸檔模式概念。開啟歸檔模式后數(shù)據(jù)庫(kù)會(huì)保存所有事務(wù)日志這樣在備份數(shù)據(jù)文件的基礎(chǔ)上再應(yīng)用日志可以把數(shù)據(jù)庫(kù)恢復(fù)到任意時(shí)間點(diǎn)。實(shí)際操作里一個(gè)值得記錄的點(diǎn)達(dá)夢(mèng)在OPEN狀態(tài)下做聯(lián)機(jī)備份默認(rèn)是備份數(shù)據(jù)庫(kù)的完整數(shù)據(jù)文件加上歸檔日志這樣才能保證恢復(fù)時(shí)數(shù)據(jù)一致性。如果只是簡(jiǎn)單備份了數(shù)據(jù)文件而沒(méi)有備份歸檔日志恢復(fù)到某個(gè)時(shí)間點(diǎn)時(shí)可能因?yàn)槿罩救笔Ф?。我測(cè)試恢復(fù)時(shí)印證了一個(gè)原則備份是一個(gè)完整流程里的其中一環(huán)備份后的驗(yàn)證也就是定期做恢復(fù)演練同樣重要。課堂上我試了一次把數(shù)據(jù)庫(kù)恢復(fù)到另一臺(tái)機(jī)器上就因?yàn)閮蛇叞惭b路徑不一致導(dǎo)致恢復(fù)失敗后來(lái)通過(guò)修改dm.ini里的配置項(xiàng)才解決。這提醒我們生產(chǎn)環(huán)境里做恢復(fù)演練不能只在同一臺(tái)機(jī)器上做跨機(jī)恢復(fù)必須提前驗(yàn)證環(huán)境差異。4.2 數(shù)據(jù)遷移工具的使用達(dá)夢(mèng)提供了兩個(gè)主要遷移工具一個(gè)是圖形化的數(shù)據(jù)遷移工具DM數(shù)據(jù)遷移工具DTS一個(gè)是命令行工具dmfldr用于快速加載數(shù)據(jù)。我課程里先用了DTS把Oracle里的模擬數(shù)據(jù)遷到DM8整個(gè)過(guò)程界面引導(dǎo)清晰選擇源庫(kù)、目標(biāo)庫(kù)、映射表結(jié)構(gòu)、開始遷移一氣呵成。用DTS遷移時(shí)有幾點(diǎn)實(shí)際經(jīng)驗(yàn)值得分享遷移前要把源端的只讀權(quán)限賬號(hào)準(zhǔn)備好避免使用高權(quán)限賬號(hào)操作生產(chǎn)庫(kù)。大表遷移時(shí)最好分批提交不然一個(gè)事務(wù)里數(shù)據(jù)量太大會(huì)消耗大量回滾段。字符集的坑非常容易出現(xiàn)。源Oracle庫(kù)是AL32UTF8目標(biāo)DM8設(shè)的GB18030的話遷移完成后中文亂碼是必然的。所以在初始化DM庫(kù)實(shí)例時(shí)就要確認(rèn)好字符集方向不能遷移到一半再改。還有一個(gè)天然坑DTS并不能把Oracle里所有的存儲(chǔ)過(guò)程、包、函數(shù)100%自動(dòng)轉(zhuǎn)換。我遷移完存儲(chǔ)過(guò)程后用disql執(zhí)行報(bào)了一些語(yǔ)法錯(cuò)誤。這些不能指望工具自動(dòng)處理只能手動(dòng)修改函數(shù)名或語(yǔ)法。4.3 導(dǎo)入導(dǎo)出實(shí)踐與數(shù)據(jù)一致性驗(yàn)證除了物理備份達(dá)夢(mèng)的邏輯備份用dexp導(dǎo)出和dimp導(dǎo)入工具完成。類似的用法是# 導(dǎo)出某個(gè)用戶的全部對(duì)象 dexp app_user/app_user_password DIRECTORY/dm/backup FILEapp_user.dmp LOGapp_user_exp.log # 導(dǎo)入到目標(biāo)庫(kù) dimp app_user/app_user_password DIRECTORY/dm/backup FILEapp_user.dmp LOGapp_user_imp.log這里要注意導(dǎo)入時(shí)如果目標(biāo)庫(kù)里已經(jīng)有同名對(duì)象通常需要先DROP或者使用忽略錯(cuò)誤的參數(shù)否則會(huì)報(bào)“對(duì)象已存在”。我在實(shí)踐時(shí)為了省事直接用了忽略錯(cuò)誤的模式結(jié)果有些表雖然導(dǎo)入報(bào)告成功但數(shù)據(jù)量對(duì)不上一查發(fā)現(xiàn)是部分約束沖突導(dǎo)致數(shù)據(jù)沒(méi)有完全導(dǎo)入。所以導(dǎo)入完成后的數(shù)據(jù)校驗(yàn)環(huán)節(jié)不能省略一定要通過(guò)COUNT(*)或者對(duì)比關(guān)鍵表的記錄數(shù)來(lái)做驗(yàn)證。導(dǎo)入導(dǎo)出還有個(gè)經(jīng)驗(yàn)大字段CLOB/BLOB多的表導(dǎo)出文件會(huì)非常大傳輸和導(dǎo)入都比較耗時(shí)。最好按照業(yè)務(wù)模塊分用戶、分表導(dǎo)出而不是一股腦全庫(kù)導(dǎo)出這樣既能減小單文件大小也方便單獨(dú)恢復(fù)某個(gè)模塊的數(shù)據(jù)。5. 常見問(wèn)題與排查技巧記錄這一塊是學(xué)習(xí)過(guò)程中最有價(jià)值的沉淀。我把這段時(shí)間遇到的各種報(bào)錯(cuò)和解決辦法整理成了一張速查表方便以后查閱。問(wèn)題現(xiàn)象可能原因解決辦法disql登錄報(bào)“登錄密碼錯(cuò)誤”密碼含特殊字符被終端轉(zhuǎn)義用簡(jiǎn)單密碼初始化登錄后ALTER USER改密碼中文顯示亂碼字符集不一致初始化實(shí)例時(shí)設(shè)UTF-8/GB18030修改客戶端NLS_LANG遠(yuǎn)程連不上數(shù)據(jù)庫(kù)防火墻未放行5236端口開放端口核對(duì)監(jiān)聽I(yíng)P是否為0.0.0.0LIMIT分頁(yè)在視圖中報(bào)錯(cuò)部分場(chǎng)景不支持LIMIT改用ROWNUM實(shí)現(xiàn)分頁(yè)大表查詢特別慢未走索引或執(zhí)行計(jì)劃有誤EXPLAIN 查看計(jì)劃優(yōu)化索引設(shè)計(jì)存儲(chǔ)過(guò)程報(bào)ORA-00942錯(cuò)誤對(duì)象名大小寫敏感或不存在確認(rèn)大小寫注意模式名schema前綴恢復(fù)備份到新機(jī)器失敗路徑不一致或控制文件找不到修改dm.ini里的路徑參數(shù)保持目錄結(jié)構(gòu)一致導(dǎo)入數(shù)據(jù)后記錄數(shù)對(duì)不上導(dǎo)入模式忽略了約束沖突導(dǎo)數(shù)據(jù)前先清理目標(biāo)表或分批導(dǎo)入后驗(yàn)證COUNT排查問(wèn)題時(shí)我發(fā)現(xiàn)達(dá)夢(mèng)的日志體系分為事件日志和SQL日志默認(rèn)情況下SQL日志可能沒(méi)完全開啟。當(dāng)遇到奇怪的SQL問(wèn)題而找不到線索時(shí)先檢查是否開啟了相關(guān)調(diào)試日志這會(huì)給你節(jié)省大量排查時(shí)間。另一個(gè)經(jīng)常被初學(xué)者忽略的點(diǎn)是達(dá)夢(mèng)的授權(quán)機(jī)制。開發(fā)版有連接數(shù)限制當(dāng)多個(gè)終端同時(shí)連接時(shí)可能會(huì)報(bào)“超出許可連接數(shù)”這是正?,F(xiàn)象不是數(shù)據(jù)庫(kù)故障。宿舍幾個(gè)人一起連著同一個(gè)數(shù)據(jù)庫(kù)實(shí)驗(yàn)庫(kù)練習(xí)的時(shí)候這個(gè)問(wèn)題沒(méi)少見??刂坪眠B接復(fù)用或者輪流操作就可以避免這個(gè)報(bào)錯(cuò)。還要補(bǔ)充一個(gè)關(guān)于大小寫的細(xì)致問(wèn)題。我在某次實(shí)驗(yàn)中建了一張表叫Student因?yàn)榇笮懨舾袇?shù)開著后面寫SQL的時(shí)候用了student小寫直接報(bào)“表或視圖不存在”。索引、列名、同義詞的大小寫也都要保持一致這在使用ORM框架時(shí)尤其要注意框架生成的SQL往往默認(rèn)小寫很容易踩坑。6. 個(gè)人實(shí)操總結(jié)與擴(kuò)展思考6.1 學(xué)習(xí)路線上的體會(huì)學(xué)DM數(shù)據(jù)庫(kù)給我的最大感受是它特別適合已經(jīng)有一定關(guān)系型數(shù)據(jù)庫(kù)基礎(chǔ)的人快速上手。因?yàn)檎Z(yǔ)法像Oracle管理理念也向Oracle靠攏所以只要你不是零基礎(chǔ)幾個(gè)小時(shí)就能完成建庫(kù)、建用戶、建表、導(dǎo)入數(shù)據(jù)這一整套操作。但對(duì)于只接觸過(guò)MySQL的人有幾點(diǎn)需要額外適應(yīng)表空間和用戶的關(guān)系需要理清既不是MySQL的“庫(kù)”也不是完全孤立的“模式”。大小寫敏感問(wèn)題要提前確認(rèn)不然SQL里到處是引號(hào)和大小寫錯(cuò)誤。數(shù)據(jù)字典視圖從information_schema那套切換到達(dá)夢(mèng)的DBA_*視圖體系查詢?cè)獢?shù)據(jù)的方式變得完全不同。我在實(shí)驗(yàn)里把之前用MySQL寫過(guò)的一個(gè)簡(jiǎn)單的圖書管理系統(tǒng)改造到了達(dá)夢(mèng)上最初花了不少時(shí)間調(diào)試大小寫和數(shù)據(jù)類型差異但調(diào)通之后整個(gè)改造過(guò)程反而變得很順暢。這讓我意識(shí)到達(dá)夢(mèng)的Oracle兼容策略對(duì)國(guó)內(nèi)大量存量系統(tǒng)來(lái)說(shuō)確實(shí)是一條務(wù)實(shí)的路。6.2 后續(xù)可以繼續(xù)挖掘的方向?qū)W完課程之后我覺(jué)得有幾個(gè)方向值得繼續(xù)深入達(dá)夢(mèng)的集群部署和高可用方案比如數(shù)據(jù)守護(hù)、讀寫分離集群。單機(jī)學(xué)起來(lái)容易生產(chǎn)環(huán)境都是要上集群的而這方面我的實(shí)踐還非常有限。性能調(diào)優(yōu)。包括參數(shù)調(diào)整緩沖區(qū)大小、并發(fā)線程數(shù)等、SQL改寫、索引優(yōu)化這些和實(shí)際業(yè)務(wù)性能強(qiáng)相關(guān)也是DBA核心價(jià)值所在。異構(gòu)數(shù)據(jù)庫(kù)遷移的完整流程。課程里只做了一個(gè)模擬庫(kù)的遷移真實(shí)場(chǎng)景里業(yè)務(wù)流程、存儲(chǔ)過(guò)程、定時(shí)任務(wù)、應(yīng)用代碼的改造成本遠(yuǎn)比想象復(fù)雜。我個(gè)人體會(huì)是國(guó)產(chǎn)數(shù)據(jù)庫(kù)的學(xué)習(xí)不能只在文檔里看一定要親手裝一遍、建一遍、備份一遍、恢復(fù)一遍、報(bào)錯(cuò)一次再排查一遍這些經(jīng)歷里學(xué)到的東西才是真正能帶到工作中去的。有一點(diǎn)心得想特別分享給剛開始接觸達(dá)夢(mèng)的朋友不要被“國(guó)產(chǎn)”兩個(gè)字帶著預(yù)設(shè)成見把它當(dāng)成一個(gè)普通的、有自己特性的數(shù)據(jù)庫(kù)產(chǎn)品去學(xué)習(xí)和使用。它的生態(tài)和工具鏈雖然不像國(guó)際老牌數(shù)據(jù)庫(kù)那么龐大但在文檔、社區(qū)、培訓(xùn)材料這些方面現(xiàn)在其實(shí)已經(jīng)相當(dāng)完整了。如果你所在的公司未來(lái)有國(guó)產(chǎn)化替代的計(jì)劃現(xiàn)在動(dòng)手學(xué)習(xí)達(dá)夢(mèng)絕對(duì)是個(gè)劃算的時(shí)間投入。