Java常見面試題匯總-----------數(shù)據(jù)庫(數(shù)據(jù)庫鎖落君、數(shù)據(jù)庫存儲過程)

57、數(shù)據(jù)庫的鎖

??鎖是一種并發(fā)控制技術(shù)亭引,鎖是用來在多個用戶同時訪問同一個數(shù)據(jù)的時候保護數(shù)據(jù)的绎速。

57.1、有 2 種基本的鎖類型

??共享(S)鎖: 多個事務(wù)可封鎖一個共享頁焙蚓;任何事務(wù)都不能修改該頁纹冤;通常是該頁被讀取完畢,S鎖立即被釋放购公。在執(zhí)行 select 語句的時候需要給操作對象(表或者一些記錄)加上共享鎖萌京,但加鎖之前需要檢查是否有排他鎖,如果沒有宏浩,則可以加共享鎖(一個對象上可以加 n 個共享鎖 )知残,否則不行。共享鎖通常在執(zhí)行完 select 語句之后被釋放比庄,當(dāng)然也有可能是在事務(wù)結(jié)束(包括正常結(jié)束和異常結(jié)束)的時候被釋放求妹,主要取決于數(shù)據(jù)庫所設(shè)置的事務(wù)隔離級別乏盐。

??排它(X)鎖: 僅允許一個事務(wù)封鎖此頁;其他任何事務(wù)必須等到 X 鎖被釋放才能對該頁進行訪問制恍;X 鎖一直到事務(wù)結(jié)束才能被釋放丑勤。執(zhí)行 insert、update吧趣、delete 語句的時候需要給操作的對象加排他鎖法竞,在加排他鎖之前必須確認(rèn)該對象上沒有其他任何鎖,一旦加上排他鎖之后强挫,就不能再給這個對象加其他任何鎖岔霸。排他鎖的釋放通常是在事務(wù)結(jié)束的時候(當(dāng)然也有例外,就是在數(shù)據(jù)庫事務(wù)隔離級別被設(shè)置成 Read Uncommitted(讀未提交數(shù)據(jù))的時候俯渤,這種情況下排他鎖會在執(zhí)行完更新操作之后就釋放呆细,而不是在事務(wù)結(jié)束的時候)。

57.2八匠、mysql 鎖的粒度(即鎖的級別)

??MySQL 各存儲引擎使用了三種類型(級別)的鎖定機制:行級鎖定絮爷,頁級鎖定和表級鎖定。
??1梨树、表級鎖坑夯, 直接鎖定整張表,在你鎖定期間抡四,其它進程無法對該表進行寫操作柜蜈。如果你是寫鎖,則其它進程則讀也不允許指巡。特點:開銷小淑履,加鎖快;不會出現(xiàn)死鎖藻雪;鎖定粒度最大秘噪,發(fā)生鎖沖突的概率最高,并發(fā)度最低勉耀。
??MyISAM 存儲引擎采用的是表級鎖指煎。
??有 2 種模式:表共享讀鎖和表獨占寫鎖。加讀鎖的命令:lock table 表名 read;去掉鎖的命令:unlock tables瑰排。
??支持并發(fā)插入:支持查詢和插入操作并發(fā)進行(在表尾并發(fā)插入)贯要。
??鎖調(diào)度機制:寫鎖優(yōu)先暖侨。一個進程請求某個 MyISAM 表的讀鎖椭住,同時另一個進程也請求同一表的寫鎖,MySQL 如何處理呢字逗?答案是寫進程先獲得鎖京郑。

??2宅广、行級鎖, 僅對指定的記錄進行加鎖些举,這樣其它進程還是可以對同一個表中的其它記錄進行操作跟狱。特點:開銷大,加鎖慢户魏;會出現(xiàn)死鎖驶臊;鎖定粒度最小,發(fā)生鎖沖突的概率最低叼丑,并發(fā)度也最高关翎。
??InnoDB 存儲引擎既支持行級鎖,也支持表級鎖鸠信,但默認(rèn)情況下是采用行級鎖纵寝。

??3、頁級鎖星立,一次鎖定相鄰的一組記錄爽茴。開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖绰垂;鎖定粒度界于表鎖和行鎖之間室奏,并發(fā)度一般。

??最常用的處理多用戶并發(fā)訪問的方法是加鎖劲装。當(dāng)一個用戶鎖住數(shù)據(jù)庫中的某個對象時窍奋,其他用戶就不能再訪問該對象。加鎖對并發(fā)訪問的影響體現(xiàn)在鎖的粒度上酱畅。比如琳袄,(表鎖)放在一個表上的鎖限制對整個表的并發(fā)訪問;(頁鎖)放在數(shù)據(jù)頁上的鎖限制了對整個數(shù)據(jù)頁的訪問纺酸;(行鎖)放在行上的鎖只限制對該行的并發(fā)訪問窖逗。

57.3、按鎖的機制分:有悲觀鎖和樂觀鎖

??悲觀鎖 餐蔬,鎖如其名碎紊,他對世界是悲觀的,他認(rèn)為別人訪問正在改變的數(shù)據(jù)的概率是很高的樊诺,所以從數(shù)據(jù)開始更改時就將數(shù)據(jù)鎖住仗考,直到更改完成才釋放。
??一個典型的倚賴數(shù)據(jù)庫的悲觀鎖調(diào)用:
??select * from account where name=”Erica” for update
??這條 sql 語句鎖定了 account 表中所有符合檢索條件(name=”Erica”)的記錄词爬。 本次事務(wù)提交之前(事務(wù)提交時會釋放事務(wù)過程中的鎖)秃嗜,外界無法修改這些記錄。該語句用來鎖定特定的行(如果有 where 子句,就是滿足 where條件的那些行)锅锨。當(dāng)這些行被鎖定后叽赊,其他會話可以選擇這些行,但不能更改或刪除這些行必搞,直到該語句的事務(wù)被 commit 語句或 rollback 語句結(jié)束為止必指。需要注意的是,select ....for update 要放到 mysql的事務(wù)中恕洲,即 begin 和commit 中塔橡,否則不起作用。
??悲觀鎖可能會造成加鎖的時間很長霜第,并發(fā)性不好谱邪,特別是長事務(wù),影響系統(tǒng)的整體性能庶诡。
??悲觀鎖的實現(xiàn)方式:
??悲觀鎖惦银,也是基于數(shù)據(jù)庫的鎖機制實現(xiàn)。 傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制末誓,比如行鎖扯俱,表鎖等,讀鎖喇澡,寫鎖等迅栅,都是在做操作之前先上鎖。

??樂觀鎖 晴玖,他對世界比較樂觀读存,認(rèn)為別人訪問正在改變的數(shù)據(jù)的概率是很低的,所以直到修改完成呕屎,準(zhǔn)備提交所做的修改到數(shù)據(jù)庫的時候才會將數(shù)據(jù)鎖住让簿, 當(dāng)你讀取以及改變該對象時并不加鎖,完成更改后釋放秀睛。樂觀鎖不能解決臟讀的問題尔当。
??樂觀鎖加鎖的時間要比悲觀鎖短,大大提升了大并發(fā)量下的系統(tǒng)整體性能表現(xiàn)蹂安。
??樂觀鎖的實現(xiàn)方式:
??1椭迎、大多是基于數(shù)據(jù)版本(Version )記錄機制實現(xiàn), 需要為每一行數(shù)據(jù)增加一個版本標(biāo)識(也就是每一行數(shù)據(jù)多一個字段 version)田盈,每次更新數(shù)據(jù)都要更新對應(yīng)的版本號+1畜号。
??工作原理:讀出數(shù)據(jù)時,將此版本號一同讀出允瞧,之后更新時简软,對此版本號加一蛮拔。 此時,將提交數(shù)據(jù)的版本信息與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進行比對替饿,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號语泽,則予以更新贸典,否則認(rèn)為是過期數(shù)據(jù)视卢,不得不重新讀取該對象并作出更改。
??假設(shè)數(shù)據(jù)庫中帳戶信息表中有一個version 字段廊驼,當(dāng)前值為 1据过;而當(dāng)前帳戶余額字段(balance)為 $100。
??1)妒挎、操作員 A 此時將其讀出(version=1)绳锅,并從其帳戶余額中扣除 $50($100-$50)。
??2)酝掩、在操作員 A 操作的過程中鳞芙,操作員 B 也讀入此用戶信息(version=1),并從其帳戶余額中扣除 $20($100-$20)期虾。
??3) 操作員 A 完成了修改工作原朝,將數(shù)據(jù)版本號加一(version=2),連同帳戶扣除后余額(balance=$50)镶苞,提交至數(shù)據(jù)庫更新喳坠,此時由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫記錄當(dāng)前版本,數(shù)據(jù)被更新茂蚓,數(shù)據(jù)庫記錄 version 更新為 2壕鹉。
??4) 操作員 B 完成了操作,也將版本號加一(version=2)試圖向數(shù)據(jù)庫提交數(shù)據(jù)(balance=$80)聋涨,但此時比對數(shù)據(jù)庫記錄版本時發(fā)現(xiàn)晾浴,操作員 B 提交的數(shù)據(jù)版本號為2,數(shù)據(jù)庫記錄當(dāng)前版本也為 2 牍白,不滿足“提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新“的樂觀鎖策略怠肋,因此,操作員 B 的提交被駁回淹朋。
??這樣笙各,就避免了操作員 B 用基于 version=1 的舊數(shù)據(jù)修改的結(jié)果覆蓋操作員 A 的操作結(jié)果的可能。
??從上面的例子可以看出础芍,樂觀鎖機制避免了長事務(wù)中的數(shù)據(jù)庫加鎖開銷(操作員 A 和操作員 B 操作過程中杈抢,都沒有對數(shù)據(jù)庫數(shù)據(jù)加鎖),大大提升了大并發(fā)量下的系統(tǒng)整體性能表現(xiàn)仑性。

??2惶楼、使用時間戳來實現(xiàn)
??同樣是在需要樂觀鎖控制的 table 中增加一個字段,名稱無所謂,字段類型使用時間戳(timestamp)歼捐,和上面的 version 類似何陆,也是在更新提交的時候檢查當(dāng)前數(shù)據(jù)庫中數(shù)據(jù)的時間戳和自己更新前取到的時間戳進行對比,如果一致則 OK豹储,否則就是版本沖突贷盲。
??悲觀鎖和樂觀鎖的適用場景:
??如果并發(fā)量不大,可以使用悲觀鎖解決并發(fā)問題剥扣;但如果系統(tǒng)的并發(fā)量非常大的話巩剖,悲觀鎖定會帶來非常大的性能問題,所以我們就要選擇樂觀鎖定的方法钠怯。



58佳魔、數(shù)據(jù)庫存儲過程

58.1、存儲過程

??存儲過程:就是一些編譯好了的 sql 語句晦炊,這些 SQL 語句代碼像一個方法一樣實現(xiàn)一些功能(對單表或多表的增刪改查)鞠鲜,然后再給這個代碼塊取一個名字,在用到這個功能的時候調(diào)用他就行了断国。
??優(yōu)點:
??1贤姆、存儲過程因為 SQL 語句已經(jīng)預(yù)編譯過了,因此運行的速度比較快并思。
??2庐氮、存儲過程在服務(wù)器端運行,減少客戶端的壓力宋彼。
??3弄砍、允許模塊化程序設(shè)計,就是說只需要創(chuàng)建一次過程输涕,以后在程序中就可以調(diào)用該過程任意次音婶,類似方法的復(fù)用。
??4莱坎、減少網(wǎng)絡(luò)流量衣式,客戶端調(diào)用存儲過程只需要傳存儲過程名和相關(guān)參數(shù)即可,與傳輸 SQL 語句相比自然數(shù)據(jù)量少了很多檐什。
??5碴卧、增強了使用的安全性,充分利用系統(tǒng)管理員可以對執(zhí)行的某一個存儲過程進行權(quán)限限制乃正,從而能夠?qū)崿F(xiàn)對某些數(shù)據(jù)訪問的限制住册,避免非授權(quán)用戶對數(shù)據(jù)的訪問,保證數(shù)據(jù)的安全瓮具。程序員直接調(diào)用存儲過程荧飞,根本不知道表結(jié)構(gòu)是什么凡人,有什么字段,沒有直接暴露表名以及字段名給程序員叹阔。
??缺點:
??調(diào)試麻煩(至少沒有像開發(fā)程序那樣容易)挠轴,可移植性不靈活(因為存儲過程是依賴于具體的數(shù)據(jù)庫)。

58.2耳幢、定義與調(diào)用存儲過程

create procedure insert_Student (_name varchar(50), _age int, out _id int)
begin
insert into student value(null,_name,_age);
select max(stuId) into _id from student;
end;

call insert_Student('wfz',23,@id);
select @id;

調(diào)用存儲過程

public class JdbcTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Connection cn = null;
        CallableStatement cstmt = null;
        try {
            //這里最好不要這么干岸晦,因為驅(qū)動名寫死在程序中了
            Class.forName("com.mysql.jdbc.Driver");
            //實際項目中,這里應(yīng)用DataSource數(shù)據(jù)帅掘,如果用框架委煤,這個數(shù)據(jù)源不需要我們編碼創(chuàng)建
            cn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
            cstmt = cn.prepareCall("{call insert_Student(?,?,?)}");
            cstmt.registerOutParameter(3,Types.INTEGER);
            cstmt.setString(1, "wangwu");
            cstmt.setInt(2, 25);
            cstmt.execute();
            //get第幾個堂油,不同的數(shù)據(jù)庫不一樣修档,建議不寫
            System.out.println(cstmt.getString(3));

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        } finally {
            try {
                if(cstmt != null)
                    cstmt.close();
                if(cn != null)
                    cn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市府框,隨后出現(xiàn)的幾起案子吱窝,更是在濱河造成了極大的恐慌,老刑警劉巖迫靖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件院峡,死亡現(xiàn)場離奇詭異,居然都是意外死亡系宜,警方通過查閱死者的電腦和手機照激,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盹牧,“玉大人俩垃,你說我怎么就攤上這事√ⅲ” “怎么了口柳?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長有滑。 經(jīng)常有香客問我跃闹,道長,這世上最難降的妖魔是什么毛好? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任望艺,我火速辦了婚禮,結(jié)果婚禮上肌访,老公的妹妹穿的比我還像新娘找默。我一直安慰自己,他們只是感情好场靴,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布啡莉。 她就那樣靜靜地躺著港准,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咧欣。 梳的紋絲不亂的頭發(fā)上浅缸,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音魄咕,去河邊找鬼衩椒。 笑死,一個胖子當(dāng)著我的面吹牛哮兰,可吹牛的內(nèi)容都是我干的毛萌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼喝滞,長吁一口氣:“原來是場噩夢啊……” “哼阁将!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起右遭,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤做盅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窘哈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吹榴,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年滚婉,在試婚紗的時候發(fā)現(xiàn)自己被綠了图筹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡让腹,死狀恐怖远剩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哨鸭,我是刑警寧澤民宿,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站像鸡,受9級特大地震影響活鹰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜只估,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一志群、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛔钙,春花似錦锌云、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彬向。三九已至,卻和暖如春攻冷,著一層夾襖步出監(jiān)牢的瞬間娃胆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工等曼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留里烦,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓禁谦,卻偏偏與公主長得像胁黑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子州泊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容