Java面試題2.0--數據庫

 

歡迎關注《Java面試題2.0》合集發佈頁,持續更新中!

 
varchar和char的使用場景
用來存儲字符
varchar適用字符長度經常變的
char適用字符長度固定的
 
Varchar2和varchar有什麼區別?
Char的長度是固定的,而varchar2的長度是可以變化的,比如,存儲字符串“abc”對於char(20),表示你存儲的字符將佔20個字節,包含17個空,而同樣的varchar2(20)只佔了3個字節,20只是最大值,當你存儲的字符小於20時,按實際長度存儲。 char的效率要被varchar2的效率高。 目前varchar是varchar2的同義詞,工業標準的varchar類型可以存儲空字符串,但是oracle不能這樣做,儘管它保留以後這樣做的權利。Oracle自己開發了一個數據類型varchar2,這個類型不是一個標準的varchar,他將在數據庫中varchar列可以存儲空字符串的特性改爲存儲null值,如果你想有向後兼容的能力,oracle建議使用varchar2而不是varchar
 
mysql 中 in 和 exists 區別。
如果查詢的兩個表大小相當,那麼用in和exists差別不大。 
如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in: 
not in 和not exists如果查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;而not extsts 的子查詢依然能用到表上的索引。所以無論那個表大,用not exists都比not in要快。 
 
1.EXISTS只返回TRUE或FALSE,不會返回UNKNOWN。
2.IN當遇到包含NULL的情況,那麼就會返回UNKNOWN。
 
String能被繼承嗎?爲什麼?
不可以,因爲String類有final修飾符,而final修飾的類是不能被繼承的,實現細節不允許改變。
 
union和union all有什麼不同?
UNION在進行錶鏈接後會篩選掉重複的記錄,所以在錶鏈接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。實際大部分應用中是不會產生重複的記錄,最常見的是過程表與歷史表UNION。 UNION ALL只是簡單的將兩個結果合併後就返回。這樣,如果返回的兩個結果集中有重複的數據,那麼返回的結果集就會包含重複的數據了。 從效率上說,UNION ALL 要比UNION快很多,所以,如果可以確認合併的兩個結果集中不包含重複的數據的話,那麼就使用UNION ALL。
 
order by與group by的區別
order by 排序查詢、asc升序、desc降序 
group by 分組查詢、having 只能用於group by子句、作用於組內,having條件子句可以直接跟函數表達式。使用group by 子句的查詢語句需要使用聚合函數。
 
 
commit在哪裏會運用
oracle的commit就是DML語句提交數據(這裏是釋放鎖不是鎖表),在未提交前你前面的操作更新的都是內存,沒有更新到物理文件中。 執行commit從用戶角度講就是更新到物理文件了,事實上commit時還沒有寫date file,而是記錄了redo log file,要從內存寫到data物理文件,需要觸發檢查點,由DBWR這個後臺進程來寫,這裏內容有點多的,如果不深究的話你就理解成commit即爲從內存更新到物理文件。
 
什麼是內連接,左外連接,右外連接?
內聯接(Inner Join):匹配2張表中相關聯的記錄。
左外聯接(Left Outer Join):除了匹配2張表中相關聯的記錄外,還會匹配左表中剩餘的記錄,右表中未匹配到的字段用NULL表示。
右外聯接(Right Outer Join):除了匹配2張表中相關聯的記錄外,還會匹配右表中剩餘的記錄,左表中未匹配到的字段用NULL表示。
在判定左表和右表時,要根據表名出現在Outer Join的左右位置關係。
 
Delete、truncaate、drop都是刪除語句,它們有什麼分別?
1).delete 屬於DML語句,刪除數據,保留表結構,需要commit,可以回滾,如果數據量大,很慢。
2).truncate 屬於DDL語句,刪除所有數據,保留表結構,自動commit,不可以回滾,一次全部刪除所有數據,速度相對較快。
3).Drop屬於 DDL語句,刪除數據和表結構,不需要commit,刪除速度最快。
 
 
存儲過程
CREATE  PROCEDURE  num_from_employee (IN emp_id INT, OUT count_num INT )  
          READS SQL DATA  
          BEGIN  
              SELECT  COUNT(*)  INTO  count_num  
              FROM  employee  
              WHERE  d_id=emp_id ;  
          END
上述代碼中,存儲過程名稱爲num_from_employee;輸入變量爲emp_id;輸出變量爲count_num。SELECT語句從employee表查詢d_id值等於emp_id的記錄,並用COUNT(*)計算d_id值相同的記錄的條數,最後將計算結果存入count_num中。
 
函數
CREATE  FUNCTION  name_from_employee (emp_id INT )  
          RETURNS VARCHAR(20)  
          BEGIN  
              RETURN  (SELECT  name  
              FROM  employee  
              WHERE  num=emp_id );  
          END
 
觸發器
CREATE TRIGGER trigger_t1
AFTER INSERT ON table2
FOR EACH ROW
UPDATE table1 SET table1.count=table1.count+1;
 
創建索引
CREATE INDEX indexName ON mytable(username(length));
如果是CHAR VARCHAR類型,length可以小於字段實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。
 
什麼是事務?什麼是鎖?
事務就是被綁定在一起作爲一個邏輯工作單元的SQL語句分組,如果任何一個語句操作失敗那麼整個操作就被失敗,以後操作就會回滾到操作前狀態,或者是上有個節點。爲了確保要麼執行,要麼不執行,就可以使用事務。要將有組語句作爲事務考慮,就需要通過ACID測試,即原子性,一致性,隔離性和持久性。
 鎖:在所以的DBMS中,鎖是實現事務的關鍵,鎖可以保證事務的完整性和併發性。與現實生活中鎖一樣,它可以使某些數據的擁有者,在某段時間內不能使用某些數據或數據結構。當然鎖還分級別的。
 
什麼是回滾?
    爲了保證在應用程序、數據庫或系統出現錯誤後,數據庫能夠被還原,以保證數據庫的完整性 ,所以需要進行回滾。回滾(rollback)就是在事務提交之前將數據庫數據恢復到事務修改之前數據庫數據狀態。
 
數據庫的樂觀鎖和悲觀鎖是什麼?
樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。
悲觀鎖:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操作
樂觀鎖:假設不會發生併發衝突,只在提交操作時檢查是否違反數據完整性。
 
什麼是封鎖?封鎖的基本類型有哪幾種?含義是什麼?
 
所謂封鎖就是當一個事務在對某個數據對象(可以是數據項、記錄、數據集、以至整個數據庫)進行操作之前,必須獲得相應的鎖,以保證數據操作的正確性和一致性。
基本的封鎖類型有兩種:排它鎖和共享鎖
(1)排它鎖:排它鎖又稱寫鎖,簡稱爲X鎖,其採用的原理是禁止併發操作。 
(2)共享鎖:共享鎖又稱讀鎖,,簡稱爲S鎖,其採用的原理是允許其他用戶對同一數據對象進行查詢,但不能對該數據對象進行修改。
 
事務四大特性
原子性,要麼執行,要麼不執行
隔離性,所有操作全部執行完以前,其它會話不能看到過程
一致性,事務前後,數據總額一致
持久性,一旦事務提交,對數據的改變就是永久的
 
數據庫隔離級別,每個級別會引發什麼問題,mysql默認是哪個級別
髒讀:事務B讀取事務A還沒有提交的數據
不可重複讀:兩次事務讀的數據不一致
幻讀:事務A修改了數據,事務B也修改了數據,這時在事務A看來,明明修改了數據,昨不一樣,
隔離級別 讀數據一致性 髒讀 不可重複讀 幻讀
 
未提交讀(Read Uncommitted):允許髒讀,也就是可能讀取到其他會話中未提交事務修改的數據
提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)
可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重複讀,但是還存在幻象讀
串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞
 
 
事務的併發問題?
 
實際場景下,事務並不是串行的,所以會帶來如下三個問題:
1、髒讀:事務 A 讀取了事務 B 更新的數據,然後 B 回滾操作,那麼 A 讀取到的數據是髒數據。
2、不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務 A 多次讀取的過程中,對數據作了更新並提交,導致事務 A 多次讀取同一數據時,結果不一致。
3、幻讀:系統管理員 A 將數據庫中所有學生的成績從具體分數改爲 ABCDE 等級,但是系統管理員 B 就在這個時候插入了一條具體分數的記錄,當系統管理員 A 改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。
 
如何維護數據庫的完整性和一致性?
儘可能使用約束,如check,主鍵,外鍵,非空字段等來約束,這樣做效率最高,也最方便。其次是使用觸發器,這種方法可以保證,無論什麼業務系統訪問數據庫都可以保證數據的完整新和一致性。最後考慮的是自寫業務邏輯,但這樣做麻煩,編程複雜,效率低下。
 
MYSQL的兩種存儲引擎區別(事務、鎖級別等等),各自的適用場景
MYISAM 不支持事務,不支持外鍵,表鎖,插入數據時,鎖定整個表,查表總行數時,不需要全表掃描
INNODB 支持事務,支持外鍵,行鎖,查表總行數時,全表掃描
 
 
Oracle和Mysql的區別?
1)庫函數不同。
2)Oracle是用表空間來管理的,Mysql不是。 
3)顯示當前所有的表、用戶、改變連接用戶、顯示當前連接用戶、執行外部腳本的語句的不同。
4)分頁查詢時候時候,mysql用limit oracle用rownum
 
MongoDB優勢與劣勢
優勢:
1、在適量級的內存的MongoDB的性能是非常迅速的,它將熱數據存儲在物理內存中,使得熱數據的讀寫變得十分快。
2、MongoDB的高可用和集羣架構擁有十分高的擴展性。
3、在副本集中,當主庫遇到問題,無法繼續提供服務的時候,副本集將選舉一個新的主庫繼續提供服務。
4、MongoDB的Bson和JSon格式的數據十分適合文檔格式的存儲與查詢。
劣勢:
1、 不支持事務操作。MongoDB本身沒有自帶事務機制,若需要在MongoDB中實現事務機制,需通過一個額外的表,從邏輯上自行實現事務。
2、 應用經驗少,由於NoSQL興起時間短,應用經驗相比關係型數據庫較少。
3、MongoDB佔用空間過大。
 
 
數據庫的主從複製
默認異步複製,容易造成主庫數據和從庫不一致
一個數據庫爲Master,一個數據庫爲slave,通過Binlog日誌
slave兩個線程,一個線程去讀master binlog日誌,寫到自己的中繼日誌
一個線程解析日誌,執行sql
master啓動一個線程
給slave傳遞binlog日誌
 
半同步複製
只有把master發送的binlog日誌寫到slave的中繼日誌,這時主庫
才返回操作完成的反饋,性能有一定降低
 
並行複製
slave 多個線程去請求binlog日誌
 
數據庫連接池的作用
維護一定數量的連接,減少創建連接的時間
更快的響應時間
統一的管理
 
數據庫三範式
1NF 屬性不可分
2NF 非主鍵屬性,完全依賴於主鍵屬性
3NF 非主鍵屬性無傳遞依賴
 
關係型數據庫和非關係型數據庫區別
類型 特性
關係型數據庫mysql 
1、關係型數據庫,是指採用了關係模型來組織數據的數據庫,
2、關係型數據庫的最大特點就是事務的一致性;
 
優點
1、容易理解:二維表結構是非常貼近邏輯世界一個概念,關係模型相對網狀、層次等其他模型來說更容易理解;
2、使用方便:通用的SQL語言使得操作關係型數據庫非常方便;
3、易於維護:豐富的完整性(實體完整性、參照完整性和用戶定義的完整性)大大減低了數據冗餘和數據不一致的概率;
4、支持SQL,可用於複雜的查詢。
缺點
1、爲了維護一致性所付出的巨大代價就是其讀寫性能比較差;
2、固定的表結構;
3、不支持高併發讀寫需求;
4、不支持海量數據的高效率讀寫;
 
非關係型數據庫 特性
HBase 
1、使用鍵值對存儲數據;
2、分佈式;
優點
無需經過sql層的解析,讀寫性能很高
基於鍵值對,數據沒有耦合性,容易擴展
存儲數據的格式:nosql的存儲格式是key,value形式
缺點
不支持事務
不提供sql支持
 
觸發器的作用?
觸發器是一中特殊的存儲過程,主要是通過事件來觸發而被執行的。它可以強化約束,來維護數據的完整性和一致性,可以跟蹤數據庫內的操作從而不允許未經許可的更新和變化。可以聯級運算。如,某表上的觸發器上包含對另一個表的數據操作,而該操作又會導致該表觸發器被觸發。
 
什麼是存儲過程?用什麼來調用?
存儲過程是一個預編譯的SQL語句,優點是允許模塊化的設計,就是說只需創建一次,以後在該程序中就可以調用多次。如果某次操作需要執行多次SQL,使用存儲過程比單純SQL語句執行要快。 
調用: 
1)可以用一個命令對象來調用存儲過程。 2)可以供外部程序調用,比如:java程序。
 
存儲過程的優缺點?
優點: 
1)存儲過程是預編譯過的,執行效率高。 2)存儲過程的代碼直接存放於數據庫中,通過存儲過程名直接調用,減少網絡通訊。 3)安全性高,執行存儲過程需要有一定權限的用戶。 4)存儲過程可以重複使用,可減少數據庫開發人員的工作量。
 缺點:移植性差
 
存儲過程與函數的區別
 
存儲過程
函數
用於在數據庫中完成特定的操作或者任務(如插入、刪除等)    
程序頭部聲明用procedure    
程序頭部聲明時不需描述返回類型    
可以使用in/out/in out 三種模式的參數    
可作爲一個獨立的PL/SQL語句來執行    
可以通過out/in out 返回零個或多個值    
SQL語句(DML 或SELECT)中不可調用存儲過程    
用於特定的數據(如選擇)
程序頭部聲明用function
程序頭部聲明時要描述返回類型,而且PL/SQL塊中至少要包括一個有效的return語句
可以使用in/out/in out 三種模式的參數
不能獨立執行,必須作爲表達式的一部分調用
通過return語句返回一個值,且改值要與聲明部分一致,也可以是通過out類型的參數帶出的變量
SQL語句(DML 或SELECT)中可以調用函數
 
 
什麼叫視圖?遊標是什麼?
視圖:是一種虛擬的表,具有和物理表相同的功能。可以對視圖進行增,改,查,操作,試圖通常是有一個表或者多個表的行或列的子集。對視圖的修改會影響基本表。它使得我們獲取數據更容易,相比多表查詢。
 遊標:是對查詢出來的結果集作爲一個單元來有效的處理。遊標可以定在該單元中的特定行,從結果集的當前行檢索一行或多行。可以對結果集當前行做修改。一般不使用遊標,但是需要逐條處理數據的時候,遊標顯得十分重要。
 
使用遊標的基本步驟有哪些?
1.聲明遊標2.打開遊標3.讀取遊標中的數據4.關閉遊標5.釋放遊標
 
視圖的優缺點
優點: 1)對數據庫的訪問,因爲視圖可以有選擇性的選取數據庫裏的一部分。 2 )用戶通過簡單的查詢可以從複雜查詢中得到結果。 3 )維護數據的獨立性,試圖可從多個表檢索數據。 4 )對於相同的數據可產生不同的視圖。 
缺點: 性能:查詢視圖時,必須把視圖的查詢轉化成對基本表的查詢,如果這個視圖是由一個複雜的多表查詢所定義,那麼,那麼就無法更改數據
 
什麼是內存泄漏?
答:一般我們所說的內存泄漏指的是堆內存的泄漏。堆內存是程序從堆中爲其分配的,大小任意的,使用完後要顯示釋放內存。當應用程序用關鍵字new等創建對象時,就從堆中爲它分配一塊內存,使用完後程序調用free或者delete釋放該內存,否則就說該內存就不能被使用,我們就說該內存被泄漏了。
 
超鍵、候選鍵、主鍵、外鍵分別是什麼?
超鍵:在關係中能唯一標識元組的屬性集稱爲關係模式的超鍵。一個屬性可以爲作爲一個超鍵,多個屬性組合在一起也可以作爲一個超鍵。超鍵包含候選鍵和主鍵。
候選鍵:是最小超鍵,即沒有冗餘元素的超鍵。
主鍵:數據庫表中對儲存數據對象予以唯一和完整標識的數據列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能爲空值(Null)。
外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵。
 
產生死鎖的原因主要是:
 
(1)系統資源不足。 
 
(2) 進程運行推進的順序不合適。 
 
(3)資源分配不當等。
 
mysql 怎麼解決死鎖。
 
1)重啓數據庫(誰用誰知道) 
2)殺掉搶資源的進程: 
先查哪些進程在搶資源:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; 
 
殺掉它們:Kill trx_mysql_thread_id;
 
Sql
 
 
 
 
一張表,裏面有 ID 自增主鍵,當 insert 了 17 條記錄之後,刪除了第 15,16,17 條記錄,再把 MySQL 重啓,再 insert 一條記錄,這條記錄的 ID 是 18 還是 15?
 
一般情況下,我們創建的表的類型是 InnoDB ,如果新增一條記錄(不重啓 MySQL 的情況下),這條記錄的 ID 是18 ;但是如果重啓 MySQL 的話,這條記錄的 ID 是 15 。因爲 InnoDB 表只把自增主鍵的最大 ID 記錄到內存中,所以重啓數據庫或者對錶 OPTIMIZE 操作,都會使最大 ID 丟失。
但是,如果我們使用表的類型是 MyISAM ,那麼這條記錄的 ID 就是 18 。因爲 MyISAM 表會把自增主鍵的最大 ID 記錄到數據文件裏面,重啓 MYSQL 後,自增主鍵的最大 ID 也不會丟失
 
 
MySQL 數據庫 CPU 飆升到 500% 的話,怎麼處理?
當 CPU 飆升到 500% 時,先用操作系統命令 top 命令觀察是不是 mysqld 佔用導致的,如果不是,找出佔用高的進程,並進行相關處理。
 
如果此時是 IO 壓力比較大,可以使用 iostat 命令,定位是哪個進程佔用了磁盤 IO 。
 
如果是 mysqld 造成的,使用 show processlist 命令,看看裏面跑的 Session 情況,是不是有消耗資源的 SQL 在運行。找出消耗高的 SQL ,看看執行計劃是否準確, index 是否缺失,或者實在是數據量太大造成。一般來說,肯定要 kill 掉這些線程(同時觀察 CPU 使用率是否下降),等進行相應的調整(比如說加索引、改 SQL 、改內存參數)之後,再重新跑這些 SQL。
 
也可以查看 MySQL 慢查詢日誌,看是否有慢 SQL 。
 
也有可能是每個 SQL 消耗資源並不多,但是突然之間,有大量的 Session 連進來導致 CPU 飆升,這種情況就需要跟應用一起來分析爲何連接數會激增,再做出相應的調整,比如說限制連接數等。
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章