某部門的一個電話面試

因爲其電話面試問的是一些基礎,剛好這些問題是我的短板,故記錄一下。

1、mysql的事務特性

原子性(Atomicity)
一致性(Consistency)
隔離性(Isolation)
持久性(Durability)

2、mysql的事務的隔離級別

Read Uncommitted(讀取未提交內容)
Read Committed(讀取提交內容)
Repeatable Read(可重讀)
Serializable(可串行化)

注意這倆問題可以與spring事務對比記憶:

什麼是事務:

事務邏輯上的一組操作,組成這組操作的各個邏輯單元,要麼一起成功,要麼一起失敗.

事務特性(4種)與數據庫一致ACID:

原子性 (atomicity):強調事務的不可分割.
一致性 (consistency):事務的執行的前後數據的完整性保持一致.
隔離性 (isolation):一個事務執行的過程中,不應該受到其他事務的干擾
持久性(durability) :事務一旦結束,數據就持久到數據庫

事務併發引起的三種情況:

  1. Dirty Reads 髒讀
    一個事務正在對數據進行更新操作,但是更新還未提交,另一個事務這時也來操作這組數據,並且讀取了前一個事務還未提交的數據,而前一個事務如果操作失敗進行了回滾,後一個事務讀取的就是錯誤數據,這樣就造成了髒讀。

  2. Non-Repeatable Reads 不可重複讀
    一個事務多次讀取同一數據,在該事務還未結束時,另一個事務也對該數據進行了操作,而且在第一個事務兩次次讀取之間,第二個事務對數據進行了更新,那麼第一個事務前後兩次讀取到的數據是不同的,這樣就造成了不可重複讀。

  3. Phantom Reads 幻讀
    第一個數據正在查詢符合某一條件的數據,這時,另一個事務又插入了一條符合條件的數據,第一個事務在第二次查詢符合同一條件的數據時,發現多了一條前一次查詢時沒有的數據,彷彿幻覺一樣,這就是幻讀。

非重複度和幻讀的區別:

非重複讀是指同一查詢在同一事務中多次進行,由於其他提交事務所做的修改或刪除,每次返回不同的結果集,此時發生非重複讀。
幻讀是指同一查詢在同一事務中多次進行,由於其他提交事務所做的插入操作,每次返回不同的結果集,此時發生幻像讀。
表面上看,區別就在於非重複讀能看見其他事務提交的修改和刪除,而幻像能看見其他事務提交的插入。

隔離級別:

  1. DEFAULT (默認)
    這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別。另外四個與JDBC的隔離級別相對應。
    數據庫Mysql 默認:可重複讀 ,Oracle 默認:讀已提交

  2. READ_UNCOMMITTED (讀未提交)
    這是事務最低的隔離級別,它允許另外一個事務可以看到這個事務未提交的數據。這種隔離級別會產生髒讀,不可重複讀和幻像讀。

  3. READ_COMMITTED (讀已提交)
    保證一個事務修改的數據提交後才能被另外一個事務讀取,另外一個事務不能讀取該事務未提交的數據。這種事務隔離級別可以避免髒讀出現,但是可能會出現不可重複讀和幻像讀。

  4. REPEATABLE_READ (可重複讀)
    這種事務隔離級別可以防止髒讀、不可重複讀,但是可能出現幻像讀。它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了不可重複讀。

  5. SERIALIZABLE(串行化)
    這是花費最高代價但是最可靠的事務隔離級別,事務被處理爲順序執行。除了防止髒讀、不可重複讀外,還避免了幻像讀。

事務的傳播行爲

PROPAGION_XXX :事務的傳播行爲

  • 保證同一個事務中
    PROPAGATION_REQUIRED 支持當前事務,如果不存在 就新建一個(默認)
    PROPAGATION_SUPPORTS 支持當前事務,如果不存在,就不使用事務
    PROPAGATION_MANDATORY 支持當前事務,如果不存在,拋出異常
  • 保證沒有在同一個事務中
    PROPAGATION_REQUIRES_NEW 如果有事務存在,掛起當前事務,創建一個新的事務
    PROPAGATION_NOT_SUPPORTED 以非事務方式運行,如果有事務存在,掛起當前事務
    PROPAGATION_NEVER 以非事務方式運行,如果有事務存在,拋出異常
    PROPAGATION_NESTED 如果當前事務存在,則嵌套事務執行

3、枚舉類的比較以及使用枚舉類設計單例模式

(1)枚舉對象是無法在程序中通過直接調用其構造方法來初始化的,也就是枚舉類型對象是線程安全的。enum 不能使用 extends 關鍵字繼承其他類,原因是它已經繼承了java.lang.Enum(java是單一繼承)。所以第一個問題就解決了,枚舉類對象比較使用==,在技術上==equals()都可以,因爲查看equals()底層也是使用的==,不過直接==是null安全的。
(2)枚舉類實現單例模式是 effective java 作者極力推薦的單例實現模式,因爲枚舉類型是線程安全的,並且只會裝載一次,設計者充分的利用了枚舉的這個特性來實現單例模式,枚舉的寫法非常簡單,而且枚舉類型是所用單例實現中唯一一種不會被破壞的單例實現模式。

public class SingletonObject{
    private SingletonObject(){
    }
    /**
     * 枚舉類型是線程安全的,並且只會裝載一次
     */
    private enum Singleton{
        INSTANCE;
        private final SingletonObject instance;

        Singleton(){
            instance = new SingletonObject();
        }

        private SingletonObject getInstance(){
            return instance;
        }
    }

    public static SingletonObject getInstance(){
    
        return Singleton.INSTANCE.getInstance();
    }
}

4、spring容器中bean的生命週期

在這裏插入圖片描述
1.Spring對Bean進行實例化(相當於程序中的new Xx())
2.Spring將值和Bean的引用注入進Bean對應的屬性中
3.如果Bean實現了BeanNameAware接口,Spring將Bean的ID傳遞給setBeanName()方法(實現BeanNameAware清主要是爲了通過Bean的引用來獲得Bean的ID,一般業務中是很少有用到Bean的ID的)
4.如果Bean實現了BeanFactoryAware接口,Spring將調用setBeanDactory(BeanFactory bf)方法並把BeanFactory容器實例作爲參數傳入。(實現BeanFactoryAware 主要目的是爲了獲取Spring容器,如Bean通過Spring容器發佈事件等)
5.如果Bean實現了ApplicationContextAwaer接口,Spring容器將調用setApplicationContext(ApplicationContext ctx)方法,把y應用上下文作爲參數傳入.(作用與BeanFactory類似都是爲了獲取Spring容器,不同的是Spring容器在調用setApplicationContext方法時會把它自己作爲setApplicationContext 的參數傳入,而Spring容器在調用setBeanDactory前需要程序員自己指定(注入)setBeanDactory裏的參數BeanFactory )
6.如果Bean實現了BeanPostProcess接口,Spring將調用它們的postProcessBeforeInitialization(預初始化)方法(作用是在Bean實例創建成功後對進行增強處理,如對Bean進行修改,增加某個功能)
7.如果Bean實現了InitializingBean接口,Spring將調用它們的afterPropertiesSet方法,作用與在配置文件中對Bean使用init-method聲明初始化的作用一樣,都是在Bean的全部屬性設置成功後執行的初始化方法。
8.如果Bean實現了BeanPostProcess接口,Spring將調用它們的postProcessAfterInitialization(後初始化)方法(作用與6的一樣,只不過6是在Bean初始化前執行的,而這個是在Bean初始化後執行的,時機不同 )
9.經過以上的工作後,Bean將一直駐留在應用上下文中給應用使用,直到應用上下文被銷燬
10.如果Bean實現了DispostbleBean接口,Spring將調用它的destory方法,作用與在配置文件中對Bean使用destory-method屬性的作用一樣,都是在Bean實例銷燬前執行的方法。
參考:Spring實戰

5、你使用了spring框架的那些功能或者模塊?

我回答了IOC、DI、AOP,感覺面試官不滿意,又問我還有什麼?spring容器給我的感覺就是一個管理者,它提供了springboot核心容器、spring上下文、springAOP、springWeb、springMVC,之後又出現了SpringBoot額,就這些。

6、說說你熟悉設計模式

我的回答:有23種,目前項目中用的最多的是策略模式。設計模式能說一整天。可以特別記憶一下單例模式、工廠方法模式、代理模式和觀察者模式。爲了吹牛啊。

7、SQL中in和exist的區別

EXISTS和IN的介紹
我們先對EXISTS和IN做一個簡單的介紹。

exists

exists對外表用loop逐條查詢,每次查詢都會查看exists的條件語句,當exists裏的條件語句能夠返回記錄行時(無論記錄行是的多少,只要能返回),條件就爲真,返回當前loop到的這條記錄;反之,如果exists裏的條件語句不能返回記錄行,則當前loop到的這條記錄被丟棄,exists的條件就像一個bool條件,當能返回結果集則爲true,不能返回結果集則爲false

如下:

select * from user where exists (select 1);

對user表的記錄逐條取出,由於子條件中的select 1永遠能返回記錄行,那麼user表的所有記錄都將被加入結果集,所以與select * from user;是一樣的。

又如下:

select * from user where exists (select * from user where user_id = 0);

可以知道對user表進行loop時,檢查條件語句(select * from user where user_id = 0),由於user_id永遠不爲0,所以條件語句永遠返回空集,條件永遠爲false,那麼user表的所有記錄都將被丟棄。

總結:如果A表有n條記錄,那麼exists查詢就是將這n條記錄逐條取出,然後判斷n遍exists條件。

in

in查詢相當於多個or條件的疊加,這個比較好理解,比如下面的查詢:

select * from user where user_id in (1, 2, 3);

等效於

select * from user where user_id = 1 or user_id = 2 or user_id = 3;

總結:in查詢就是先將子查詢條件的記錄全都查出來,假設結果集爲B,共有m條記錄,然後再將子查詢條件的結果集分解成m個,再進行m次查詢。

使用上的區別

in查詢的子條件返回結果必須只有一個字段,例如

select * from user where user_id in (select id from B);

不能是

select * from user where user_id in (select id, age from B);

而exists就沒有這個限制。

最後

沒有任何準備的情況下不要面試,中午剛吃了飯,還沒睡午覺就被問蒙了。因爲面試官永遠會問你的短板。我很好奇他們怎麼知道我的這些短板的,哈哈。這次電話面試,我自己都覺得我菜的一筆,不要慌,準備一下,再次起航。

參考:
https://www.zhihu.com/question/38597960
https://www.cnblogs.com/eunice-sun/p/11024584.html
https://cloud.tencent.com/developer/article/1144244
http://www.dba-oracle.com/t_exists_clause_vs_in_clause.htm
https://www.cnblogs.com/wxw16/p/6105624.html

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