2019年java中高級java面試題(三)mysql

1、 樂觀鎖與悲觀鎖的區別?


悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關係型數據庫裏邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

 

樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖

2 、事務的特性


原子性:(Atomicity)

原子性:強調事務的不可分割.

一致性:(Consistency)

一致性:事務在執行的前後,數據的完整性保持一致.

隔離性:(Isolation)

隔離性:多個事務併發執行的時候,一個事務的執行不應該受到其他的事務的干擾.

持久性:(Durability)

持久性:事務一個結束了.數據就永久的保存到數據庫.

 

3 、不考慮事務的隔離性引發的一系列安全問題


* 髒讀      :一個事務讀到了另一個事務未提交的數據.

* 不可重複讀 :一個事務讀到了另一個事務已經提交的update的數據,導致在一個事務中多次的查詢結果不一致.

* 虛讀/幻讀  :一個事務讀到了另一個事務已經提交的insert的數據,導致在一個事務中多次查詢的結果不一致.

* 數據庫中提供了事務的隔離級別用於解決三類讀問題.

* read uncommitted  :未提交讀.髒讀、不可重複讀、虛讀都是有可能發生.

* read committed    :已提交讀.避免髒讀.但是不可重複讀、虛讀是有可能發生.

* repeatable read   :可重複讀.避免髒讀、不可重複讀.但是虛讀是有可能發生.

* serializable      :串行化的.避免髒讀、不可重複讀、虛讀的發生.

 

* 安全性:serializable > repeatable read > read committed > read uncommitted

* 效率性:read uncommitted > read committed > repeatable read > serializable

 

***** MYSQL數據庫默認隔離級別:repeatable read .Oracle數據庫默認的隔離級別:read committed

 

4、 mysql常用的數據庫引擎
 

 

InnoDB:支持事務處理,支持外鍵,支持崩潰修復能力和併發控制。如果需要對事務的完整性要求比較高(比如銀行),要求實現併發控制(比如售票),那選擇InnoDB有很大的優勢。如果需要頻繁的更新、刪除操作的數據庫,也可以選擇InnoDB,因爲支持事務的提交(commit)和回滾(rollback)。

 InnoDB是提供了提交,回滾和崩潰恢復能力的事物安全存儲引擎,支持行鎖定和外鍵,是mysql的默認存儲引擎

MyISAM:插入數據快,空間和內存使用比較低。如果表主要是用於插入新記錄和讀出記錄,那麼選擇MyISAM能實現處理高效率。如果應用的完整性、併發性要求比較低,也可以使用。

MyISAM不支持事物 插入和查詢的處理效率高,支持索引

MEMORY:所有的數據都在內存中,數據的處理速度快,但是安全性不高。如果需要很快的讀寫速度,對數據的安全性要求較低,可以選擇MEMOEY。它對錶的大小有要求,不能建立太大的表。所以,這類數據庫只使用在相對較小的數據庫表。

 

5、 jdbc中Statement與Preparestament的區別


第一:

prepareStatement會先初始化SQL,先把這個SQL提交到數據庫中進行預處理,多次使用可提高效率。

Statement不會初始化,沒有預處理.

第二:

prepareStatement可以替換變量在SQL語句中可以包含?,可以用

ps=conn.prepareStatement("select* from Cust where ID=?");
 
int sid=1001;
 
ps.setInt(1, sid);
 
rs = ps.executeQuery();


可以把?替換成變量。

而Statement只能用

int sid=1001;
 
Statement stmt = conn.createStatement();
 
ResultSet rs = stmt.executeQuery("select * from Cust where ID="+sid);


來實現。

 

第三:

prepareStatement會先初始化SQL,先把這個SQL提交到數據庫中進行預處理,多次使用可提高效率。

Statement不會初始化,沒有預處理,沒次都是從0開始執行SQL

6、 sql優化

insert優化

1、如果需要對同一個表插入很多行數據時,儘量使用多個值表的sql語句

insert into tb_test values(1,'張三'),(2,'TOM'),(3,'JERRY');

 

2、在事務中進行數據插入

start transaction
insert into tb_test values(1,'張三');
insert into tb_test values(2,'TOM');
insert into tb_test values(3,'JERRY');
commit;

 

rewriteBatchedStatements=true,mysql默認關閉了batch處理,通過此參數進行打開

order by優化

Using filesort

Using index

儘量減少額外排序通過索引直接返回有序數據,通過建立合適的索引減少Filesort的出現

mysql兩種排序算法

兩次掃描算法:首先根據條件取出排序字段和指針信息,在排序區中排序,完成排序後,根據行指針回表讀取記錄

一次掃描算法:一次性取出滿足條件的所有字段在排序區排序後直接輸出結果

可以提高sort_buffer_sizemax_length_for_sort_data系統變量,增大排序區大小,調高排序效率

group by優化

group by會進行額外的排序操作

select age,count(*) from emp group by age order by null;

 

 

查詢優化
1、對查詢進行優化,要儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2、應儘量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,最好不要給數據庫留NULL,儘可能的使用 NOT NULL填充數據庫.
3、應儘量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。
4、應儘量避免在 where 子句中使用 or 來連接條件,如果一個字段有索引,一個字段沒有索引,將導致引擎放棄使用索引而進行全表掃描,如:

 

select id from t where num=10 or Name = 'admin'


可以這樣查詢:

select id from t where num = 10
 
union all
 
select id from t where Name = 'admin'


 

5、in 和 not in 也要慎用,否則會導致全表掃描

6、創建適合的索引

  例如我們建立了一個這樣的索引(area,age,salary),那麼其實相當於創建了(area,age,salary),(area,age),(area)三個索引

7、like語句優化

SELECT id FROM A WHERE name like '%abc%'
   由於abc前面用了“%”,因此該查詢必然走全表查詢,除非必要,否則不要在關鍵詞前加%,優化成如下

SELECT id FROM A WHERE name like 'abc%'
 

8、儘量用內連接替換外鏈接,用外鏈接替換子查詢。


 

7、分庫分表

 

8、oracle數據庫的分頁

select t1.*
 
  from (select rownum rw, k.*
 
from ks_collect_pushed k
 
where rownum < = 15) t1
 
 where rw > 5

9、mysql索引分類

1、普通索引

普通索引:允許列中插入重複值和空值

2、唯一索引

唯一索引:索引列的值必須唯一,但允許由空值

3、主鍵索引

主鍵索引,索引列的值必須唯一,切不允許有空值

4、聯合索引

聯合索引又叫複合索引。對於複合索引:Mysql從左到右的使用索引中的字段,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c). 可以支持a | a,ba,b,c 3種組合進行查找,但不支持 b,c進行查找 .當最左側字段是常量引用時,索引就十分有效。

5、全文索引

全文索引類型FULLTEXT,可以在CHAR、VARCHAR、TEXT上創建,只有MYIDAM存儲引擎支持

6、空間索引

空間索引是對空間數據類型的字段建立的索引,mysql中的空間數據類型有4種,分別是:GEOMETRY、POINT、LINESTRING、PLYGON。mysql使用SPATIAL創建索引,空間索引的列爲NOTNULL

 

10、MySQL存儲引擎MyISAM與InnoDB區別 

1) 事務支持
MyISAM不支持事務,而InnoDB支持。

2) 存儲結構
MyISAM:每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義。數據文件的擴展名爲.MYD (MYData)。索引文件的擴展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一個數據文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操作系統文件的大小,一般爲2GB。

3) 存儲空間
MyISAM:可被壓縮,存儲空間較小。支持三種不同的存儲格式:靜態表(默認,但是注意數據末尾不能有空格,會被去掉)、動態表、壓縮表。
InnoDB:需要更多的內存和存儲,它會在主內存中建立其專用的緩衝池用於高速緩衝數據和索引。

4) 可移植性、備份及恢復
MyISAM:數據是以文件的形式存儲,所以在跨平臺的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。
InnoDB:免費的方案可以是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了。

5) 事務支持
MyISAM:強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但是不提供事務支持。
InnoDB:提供事務支持事務,外部鍵等高級數據庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。

6) AUTO_INCREMENT
MyISAM:可以和其他字段一起建立聯合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,他可以根據前面幾列進行排序後遞增。
InnoDB:InnoDB中必須包含只有該字段的索引。引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。

7) 表鎖差異
MyISAM:只支持表級鎖,用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的數據。
InnoDB:支持事務和行級鎖,是innodb的最大特色。行鎖大幅度提高了多用戶併發操作的新能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

MyISAM鎖的粒度是表級,而InnoDB支持行級鎖定。簡單來說就是, InnoDB支持數據行鎖定,而MyISAM不支持行鎖定,只支持鎖定整個表。即MyISAM同一個表上的讀鎖和寫鎖是互斥的,MyISAM併發讀寫時如果等待隊列中既有讀請求又有寫請求,默認寫請求的優先級高,即使讀請求先到,所以MyISAM不適合於有大量查詢和修改並存的情況,那樣查詢進程會長時間阻塞。因爲MyISAM是鎖表,所以某項讀操作比較耗時會使其他寫進程餓死。

8) 全文索引
MyISAM:支持(FULLTEXT類型的)全文索引
InnoDB:不支持(FULLTEXT類型的)全文索引,但是innodb可以使用sphinx插件支持全文索引,並且效果更好。

9) 表主鍵
MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保存行的地址。
InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。InnoDB的主鍵範圍更大,最大是MyISAM的2倍。

10) 表的具體行數
MyISAM:保存有表的總行數,如果select count(*) from table;會直接取出出該值。
InnoDB:沒有保存表的總行數(只能遍歷),如果使用select count(*) from table;就會遍歷整個表,消耗相當大,但是在加了wehre條件後,myisam和innodb處理的方式都一樣。

11) CURD操作
MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇。
InnoDB:如果你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表。DELETE 從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空保存有大量數據的表,最好使用truncate table這個命令。

12) 外鍵
MyISAM:不支持
InnoDB:支持


11、mysql 內存優化

1、將盡量多的內存給mysql作緩存

2、MyISAM存儲文件的讀取依賴於操作系統自身IO緩存

 

12、Innodb內存優化

Innodb用一塊內存做io緩存池,該緩存池不僅緩存innodb索引塊,也用來緩存innodb的數據塊

innodb_buffer_pool_size

索引塊和數據塊最大的內存

innodb_log_buffer_size

決定了innodb重做日誌緩存的大小

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章