成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

包含postgresql解鎖的詞條

postgresql怎么解鎖表

--查詢是否鎖表了

創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計制作、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的長陽網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

1、select oid from pg_class where relname='可能被鎖掉的表的表名'

,會顯示一個oid

2、select pid from pg_locks where relation='剛剛查出來的oid'

--如果查詢到了結(jié)果(pid),表示該表被鎖 則需要釋放鎖定

select pg_cancel_backend(上面查到的pid)

事務(wù)的隔離級別 全部都是共享鎖嗎

前言:我們都知道事務(wù)的幾種性質(zhì),數(shù)據(jù)庫為了維護這些性質(zhì),尤其是一致性和隔離性,一般使用加鎖這種方式。同時數(shù)據(jù)庫又是個高并發(fā)的應(yīng)用,同一時間會有大量的并發(fā)訪問,如果加鎖過度,會極大的降低并發(fā)處理能力。所以對于加鎖的處理,可以說就是數(shù)據(jù)庫對于事務(wù)處理的精髓所在。這里通過分析MySQL中InnoDB引擎的加鎖機制,來拋磚引玉,讓讀者更好的理解,在事務(wù)處理中數(shù)據(jù)庫到底做了什么。一次封鎖or兩段鎖?因為有大量的并發(fā)訪問,為了預(yù)防死鎖,一般應(yīng)用中推薦使用一次封鎖法,就是在方法的開始階段,已經(jīng)預(yù)先知道會用到哪些數(shù)據(jù),然后全部鎖住,在方法運行之后,再全部解鎖。這種方式可以有效的避免循環(huán)死鎖,但在數(shù)據(jù)庫中卻不適用,因為在事務(wù)開始階段,數(shù)據(jù)庫并不知道會用到哪些數(shù)據(jù)。數(shù)據(jù)庫遵循的是兩段鎖協(xié)議,將事務(wù)分成兩個階段,加鎖階段和解鎖階段(所以叫兩段鎖)加鎖階段:在該階段可以進(jìn)行加鎖操作。在對任何數(shù)據(jù)進(jìn)行讀操作之前要申請并獲得S鎖(共享鎖,其它事務(wù)可以繼續(xù)加共享鎖,但不能加排它鎖),在進(jìn)行寫操作之前要申請并獲得X鎖(排它鎖,其它事務(wù)不能再獲得任何鎖)。加鎖不成功,則事務(wù)進(jìn)入等待狀態(tài),直到加鎖成功才繼續(xù)執(zhí)行。解鎖階段:當(dāng)事務(wù)釋放了一個封鎖以后,事務(wù)進(jìn)入解鎖階段,在該階段只能進(jìn)行解鎖操作不能再進(jìn)行加鎖操作。事務(wù) 加鎖/解鎖處理begin; insert into test ..... 加insert對應(yīng)的鎖update test set... 加update對應(yīng)的鎖delete from test .... 加delete對應(yīng)的鎖commit; 事務(wù)提交時,同時釋放insert、update、delete對應(yīng)的鎖這種方式雖然無法避免死鎖,但是兩段鎖協(xié)議可以保證事務(wù)的并發(fā)調(diào)度是串行化(串行化很重要,尤其是在數(shù)據(jù)恢復(fù)和備份的時候)的。事務(wù)中的加鎖方式事務(wù)的四種隔離級別在數(shù)據(jù)庫操作中,為了有效保證并發(fā)讀取數(shù)據(jù)的正確性,提出的事務(wù)隔離級別。我們的數(shù)據(jù)庫鎖,也是為了構(gòu)建這些隔離級別存在的。隔離級別 臟讀(Dirty Read) 不可重復(fù)讀(NonRepeatable Read) 幻讀(Phantom Read)未提交讀(Read uncommitted) 可能 可能 可能 已提交讀(Read committed) 不可能 可能 可能 可重復(fù)讀(Repeatable read) 不可能 不可能 可能 可串行化(Serializable ) 不可能 不可能 不可能 未提交讀(Read Uncommitted):允許臟讀,也就是可能讀取到其他會話中未提交事務(wù)修改的數(shù)據(jù)提交讀(Read Committed):只能讀取到已經(jīng)提交的數(shù)據(jù)。Oracle等多數(shù)數(shù)據(jù)庫默認(rèn)都是該級別 (不重復(fù)讀)可重復(fù)讀(Repeated Read):可重復(fù)讀。在同一個事務(wù)內(nèi)的查詢都是事務(wù)開始時刻一致的,InnoDB默認(rèn)級別。在SQL標(biāo)準(zhǔn)中,該隔離級別消除了不可重復(fù)讀,但是還存在幻象讀串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞Read Uncommitted這種級別,數(shù)據(jù)庫一般都不會用,而且任何操作都不會加鎖,這里就不討論了。MySQL中鎖的種類MySQL中鎖的種類很多,有常見的表鎖和行鎖,也有新加入的Metadata Lock等等,表鎖是對一整張表加鎖,雖然可分為讀鎖和寫鎖,但畢竟是鎖住整張表,會導(dǎo)致并發(fā)能力下降,一般是做ddl處理時使用。行鎖則是鎖住數(shù)據(jù)行,這種加鎖方法比較復(fù)雜,但是由于只鎖住有限的數(shù)據(jù),對于其它數(shù)據(jù)不加限制,所以并發(fā)能力強,MySQL一般都是用行鎖來處理并發(fā)事務(wù)。這里主要討論的也就是行鎖。Read Committed(讀取提交內(nèi)容)在RC級別中,數(shù)據(jù)的讀取都是不加鎖的,但是數(shù)據(jù)的寫入、修改和刪除是需要加鎖的。效果如下MySQL show create table class_teacher \G\ Table: class_teacher Create Table: CREATE TABLE `class_teacher` ( `id` int(11) NOT NULL AUTO_INCREMENT, `class_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `teacher_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `idx_teacher_id` (`teacher_id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 1 row in set (0.02 sec) MySQL select * from class_teacher; +----+--------------+------------+ id class_name teacher_id +----+--------------+------------+ 1 初三一班 1 3 初二一班 2 4 初二二班 2 +----+--------------+------------+ 由于MySQL的InnoDB默認(rèn)是使用的RR級別,所以我們先要將該session開啟成RC級別,并且設(shè)置binlog的模式SET session transaction isolation level read committed; SET SESSION binlog_format = 'ROW'; (或者是MIXED)事務(wù)A 事務(wù)Bbegin; begin;update class_teacher set class_name='初三二班' where teacher_id=1; update class_teacher set class_name='初三三班' where teacher_id=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction commit; 為了防止并發(fā)過程中的修改沖突,事務(wù)A中MySQL給teacher_id=1的數(shù)據(jù)行加鎖,并一直不commit(釋放鎖),那么事務(wù)B也就一直拿不到該行鎖,wait直到超時。這時我們要注意到,teacher_id是有索引的,如果是沒有索引的class_name呢?update class_teacher set teacher_id=3 where class_name = '初三一班';那么MySQL會給整張表的所有數(shù)據(jù)行的加行鎖。這里聽起來有點不可思議,但是當(dāng)sql運行的過程中,MySQL并不知道哪些數(shù)據(jù)行是 class_name = '初三一班'的(沒有索引嘛),如果一個條件無法通過索引快速過濾,存儲引擎層面就會將所有記錄加鎖后返回,再由MySQL Server層進(jìn)行過濾。但在實際使用過程當(dāng)中,MySQL做了一些改進(jìn),在MySQL Server過濾條件,發(fā)現(xiàn)不滿足后,會調(diào)用unlock_row方法,把不滿足條件的記錄釋放鎖 (違背了二段鎖協(xié)議的約束)。這樣做,保證了最后只會持有滿足條件記錄上的鎖,但是每條記錄的加鎖操作還是不能省略的??梢娂词故荕ySQL,為了效率也是會違反規(guī)范的。(參見《高性能MySQL》中文第三版p181)這種情況同樣適用于MySQL的默認(rèn)隔離級別RR。所以對一個數(shù)據(jù)量很大的表做批量修改的時候,如果無法使用相應(yīng)的索引,MySQL Server過濾數(shù)據(jù)的的時候特別慢,就會出現(xiàn)雖然沒有修改某些行的數(shù)據(jù),但是它們還是被鎖住了的現(xiàn)象。Repeatable Read(可重讀)這是MySQL中InnoDB默認(rèn)的隔離級別。我們姑且分“讀”和“寫”兩個模塊來講解。讀讀就是可重讀,可重讀這個概念是一事務(wù)的多個實例在并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù)據(jù)行,有點抽象,我們來看一下效果。RC(不可重讀)模式下的展現(xiàn)事務(wù)A 事務(wù)Bbegin; begin; select id,class_name,teacher_id from class_teacher where teacher_id=1; id class_name teacher_id 1 初三二班 1 2 初三一班 1 update class_teacher set class_name='初三三班' where id=1; commit; select id,class_name,teacher_id from class_teacher where teacher_id=1; id class_name teacher_id 1 初三三班 1 2 初三一班 1 讀到了事務(wù)B修改的數(shù)據(jù),和第一次查詢的結(jié)果不一樣,是不可重讀的。commit; 事務(wù)B修改id=1的數(shù)據(jù)提交之后,事務(wù)A同樣的查詢,后一次和前一次的結(jié)果不一樣,這就是不可重讀(重新讀取產(chǎn)生的結(jié)果不一樣)。這就很可能帶來一些問題,那么我們來看看在RR級別中MySQL的表現(xiàn):事務(wù)A 事務(wù)B 事務(wù)Cbegin; begin; begin; select id,class_name,teacher_id from class_teacher where teacher_id=1; id class_name teacher_id 1 初三二班 1 2 初三一班 1 update class_teacher set class_name='初三三班' where id=1; commit; insert into class_teacher values (null,'初三三班',1); commit; select id,class_name,teacher_id from class_teacher where teacher_id=1; id class_name teacher_id 1 初三二班 1 2 初三一班 1 沒有讀到事務(wù)B修改的數(shù)據(jù),和第一次sql讀取的一樣,是可重復(fù)讀的。沒有讀到事務(wù)C新添加的數(shù)據(jù)。commit; 我們注意到,當(dāng)teacher_id=1時,事務(wù)A先做了一次讀取,事務(wù)B中間修改了id=1的數(shù)據(jù),并commit之后,事務(wù)A第二次讀到的數(shù)據(jù)和第一次完全相同。所以說它是可重讀的。那么MySQL是怎么做到的呢?這里姑且賣個關(guān)子,我們往下看。不可重復(fù)讀和幻讀的區(qū)別很多人容易搞混不可重復(fù)讀和幻讀,確實這兩者有些相似。但不可重復(fù)讀重點在于update和delete,而幻讀的重點在于insert。如果使用鎖機制來實現(xiàn)這兩種隔離級別,在可重復(fù)讀中,該sql第一次讀取到數(shù)據(jù)后,就將這些數(shù)據(jù)加鎖,其它事務(wù)無法修改這些數(shù)據(jù),就可以實現(xiàn)可重復(fù)讀了。但這種方法卻無法鎖住insert的數(shù)據(jù),所以當(dāng)事務(wù)A先前讀取了數(shù)據(jù),或者修改了全部數(shù)據(jù),事務(wù)B還是可以insert數(shù)據(jù)提交,這時事務(wù)A就會發(fā)現(xiàn)莫名其妙多了一條之前沒有的數(shù)據(jù),這就是幻讀,不能通過行鎖來避免。需要Serializable隔離級別 ,讀用讀鎖,寫用寫鎖,讀鎖和寫鎖互斥,這么做可以有效的避免幻讀、不可重復(fù)讀、臟讀等問題,但會極大的降低數(shù)據(jù)庫的并發(fā)能力。所以說不可重復(fù)讀和幻讀最大的區(qū)別,就在于如何通過鎖機制來解決他們產(chǎn)生的問題。上文說的,是使用悲觀鎖機制來處理這兩種問題,但是MySQL、ORACLE、PostgreSQL等成熟的數(shù)據(jù)庫,出于性能考慮,都是使用了以樂觀鎖為理論基礎(chǔ)的MVCC(多版本并發(fā)控制)來避免這兩種問題。悲觀鎖和樂觀鎖悲觀鎖正如其名,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機制(也只有數(shù)據(jù)庫層提供的鎖機制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實現(xiàn)了加鎖機制,也無法保證外部系統(tǒng)不會修改數(shù)據(jù))。在悲觀鎖的情況下,為了保證事務(wù)的隔離性,就需要一致性鎖定讀。讀取數(shù)據(jù)時給加鎖,其它事務(wù)無法修改這些數(shù)據(jù)。修改刪除數(shù)據(jù)時也要加鎖,其它事務(wù)無法讀取這些數(shù)據(jù)。樂觀鎖相對悲觀鎖而言,樂觀鎖機制采取了更加寬松的加鎖機制。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫的鎖機制實現(xiàn),以保證操作最大程度的獨占性。但隨之而來的就是數(shù)據(jù)庫性能的大量開銷,特別是對長事務(wù)而言,這樣的開銷往往無法承受。而樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基于數(shù)據(jù)版本( Version )記錄機制實現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個 “version” 字段來實現(xiàn)。讀取出數(shù)據(jù)時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。要說明的是,MVCC的實現(xiàn)沒有固定的規(guī)范,每個數(shù)據(jù)庫都會有不同的實現(xiàn)方式,這里討論的是InnoDB的MVCC。MVCC在MySQL的InnoDB中的實現(xiàn)在InnoDB中,會在每行數(shù)據(jù)后添加兩個額外的隱藏的值來實現(xiàn)MVCC,這兩個值一個記錄這行數(shù)據(jù)何時被創(chuàng)建,另外一個記錄這行數(shù)據(jù)何時過期(或者被刪除)。 在實際操作中,存儲的并不是時間,而是事務(wù)的版本號,每開啟一個新事務(wù),事務(wù)的版本號就會遞增。 在可重讀Repeatable reads事務(wù)隔離級別下:SELECT時,讀取創(chuàng)建版本號=當(dāng)前事務(wù)版本號,刪除版本號為空或當(dāng)前事務(wù)版本號。 INSERT時,保存當(dāng)前事務(wù)版本號為行的創(chuàng)建版本號 DELETE時,保存當(dāng)前事務(wù)版本號為行的刪除版本號 UPDATE時,插入一條新紀(jì)錄,保存當(dāng)前事務(wù)版本號為行創(chuàng)建版本號,同時保存當(dāng)前事務(wù)版本號到原來刪除的行 通過MVCC,雖然每行記錄都需要額外的存儲空間,更多的行檢查工作以及一些額外的維護工作,但可以減少鎖的使用,大多數(shù)讀操作都不用加鎖,讀數(shù)據(jù)操作很簡單,性能很好,并且也能保證只會讀取到符合標(biāo)準(zhǔn)的行,也只鎖住必要行。 我們不管從數(shù)據(jù)庫方面的教課書中學(xué)到,還是從網(wǎng)絡(luò)上看到,大都是上文中事務(wù)的四種隔離級別這一模塊列出的意思,RR級別是可重復(fù)讀的,但無法解決幻讀,而只有在Serializable級別才能解決幻讀。于是我就加了一個事務(wù)C來展示效果。在事務(wù)C中添加了一條teacher_id=1的數(shù)據(jù)commit,RR級別中應(yīng)該會有幻讀現(xiàn)象,事務(wù)A在查詢teacher_id=1的數(shù)據(jù)時會讀到事務(wù)C新加的數(shù)據(jù)。但是測試后發(fā)現(xiàn),在MySQL中是不存在這種情況的,在事務(wù)C提交后,事務(wù)A還是不會讀到這條數(shù)據(jù)??梢娫贛ySQL的RR級別中,是解決了幻讀的讀問題的。參見下圖讀問題解決了,根據(jù)MVCC的定義,并發(fā)提交數(shù)據(jù)時會出現(xiàn)沖突,那么沖突時如何解決呢?我們再來看看InnoDB中RR級別對于寫數(shù)據(jù)的處理?!白x”與“讀”的區(qū)別可能有讀者會疑惑,事務(wù)的隔離級別其實都是對于讀數(shù)據(jù)的定義,但到了這里,就被拆成了讀和寫兩個模塊來講解。這主要是因為MySQL中的讀,和事務(wù)隔離級別中的讀,是不一樣的。我們且看,在RR級別中,通過MVCC機制,雖然讓數(shù)據(jù)變得可重復(fù)讀,但我們讀到的數(shù)據(jù)可能是歷史數(shù)據(jù),是不及時的數(shù)據(jù),不是數(shù)據(jù)庫當(dāng)前的數(shù)據(jù)!這在一些對于數(shù)據(jù)的時效特別敏感的業(yè)務(wù)中,就很可能出問題。對于這種讀取歷史數(shù)據(jù)的方式,我們叫它快照讀 (snapshot read),而讀取數(shù)據(jù)庫當(dāng)前版本數(shù)據(jù)的方式,叫當(dāng)前讀 (current read)。很顯然,在MVCC中:快照讀:就是selectselect * from table ....; 當(dāng)前讀:特殊的讀操作,插入/更新/刪除操作,屬于當(dāng)前讀,處理的都是當(dāng)前的數(shù)據(jù),需要加鎖。select * from table where ? lock in share mode; select * from table where ? for update; insert; update ; delete; 事務(wù)的隔離級別實際上都是定義了當(dāng)前讀的級別,MySQL為了減少鎖處理(包括等待其它鎖)的時間,提升并發(fā)能力,引入了快照讀的概念,使得select不用加鎖。而update、insert這些“當(dāng)前讀”,就需要另外的模塊來解決了。寫("當(dāng)前讀")事務(wù)的隔離級別中雖然只定義了讀數(shù)據(jù)的要求,實際上這也可以說是寫數(shù)據(jù)的要求。上文的“讀”,實際是講的快照讀;而這里說的“寫”就是當(dāng)前讀了。為了解決當(dāng)前讀中的幻讀問題,MySQL事務(wù)使用了Next-Key鎖。Next-Key鎖Next-Key鎖是行鎖和GAP(間隙鎖)的合并,行鎖上文已經(jīng)介紹了,接下來說下GAP間隙鎖。行鎖可以防止不同事務(wù)版本的數(shù)據(jù)修改提交時造成數(shù)據(jù)沖突的情況。但如何避免別的事務(wù)插入數(shù)據(jù)就成了問題。我們可以看看RR級別和RC級別的對比RC級別:事務(wù)A 事務(wù)Bbegin; begin; select id,class_name,teacher_id from class_teacher where teacher_id=30; id class_name teacher_id 2 初三二班 30 update class_teacher set class_name='初三四班' where teacher_id=30; insert into class_teacher values (null,'初三二班',30); commit; select id,class_name,teacher_id from class_teacher where teacher_id=30; id class_name teacher_id 2 初三四班 30 10 初三二班 30 RR級別: 事務(wù)A 事務(wù)B begin; begin; select id,class_name,teacher_id from class_teacher where teacher_id=30; id class_name teacher_id 2 初三二班 30 update class_teacher set class_name='初三四班' where teacher_id=30; insert into class_teacher values (null,'初三二班',30); waiting.... select id,class_name,teacher_id from class_teacher where teacher_id=30; id class_name teacher_id 2 初三四班 30 commit; 事務(wù)Acommit后,事務(wù)B的insert執(zhí)行。通過對比我們可以發(fā)現(xiàn),在RC級別中,事務(wù)A修改了所有teacher_id=30的數(shù)據(jù),但是當(dāng)事務(wù)Binsert進(jìn)新數(shù)據(jù)后,事務(wù)A發(fā)現(xiàn)莫名其妙多了一行teacher_id=30的數(shù)據(jù),而且沒有被之前的update語句所修改,這就是“當(dāng)前讀”的幻讀。RR級別中,事務(wù)A在update后加鎖,事務(wù)B無法插入新數(shù)據(jù),這樣事務(wù)A在update前后讀的數(shù)據(jù)保持一致,避免了幻讀。這個鎖,就是Gap鎖。MySQL是這么實現(xiàn)的:在class_teacher這張表中,teacher_id是個索引,那么它就會維護一套B+樹的數(shù)據(jù)關(guān)系,為了簡化,我們用鏈表結(jié)構(gòu)來表達(dá)(實際上是個樹形結(jié)構(gòu),但原理相同)如圖所示,InnoDB使用的是聚集索引,teacher_id身為二級索引,就要維護一個索引字段和主鍵id的樹狀結(jié)構(gòu)(這里用鏈表形式表現(xiàn)),并保持順序排列。Innodb將這段數(shù)據(jù)分成幾個個區(qū)間(negative infinity, 5], (5,30], (30,positive infinity); update class_teacher set class_name='初三四班' where teacher_id=30; 不僅用行鎖,鎖住了相應(yīng)的數(shù)據(jù)行;同時也在兩邊的區(qū)間,(5,30]和(30,positive infinity),都加入了gap鎖。這樣事務(wù)B就無法在這個兩個區(qū)間insert進(jìn)新數(shù)據(jù)。受限于這種實現(xiàn)方式,Innodb很多時候會鎖住不需要鎖的區(qū)間。如下所示:事務(wù)A 事務(wù)B 事務(wù)Cbegin; begin; begin; select id,class_name,teacher_id from class_teacher; id class_name teacher_id 1 初三一班 5 2 初三二班 30 update class_teacher set class_name='初一一班' where teacher_id=20; insert into class_teacher values (null,'初三五班',10); waiting ..... insert into class_teacher values (null,'初三五班',40); commit; 事務(wù)A commit之后,這條語句才插入成功 commit; commit; update的teacher_id=20是在(5,30]區(qū)間,即使沒有修改任何數(shù)據(jù),Innodb也會在這個區(qū)間加gap鎖,而其它區(qū)間不會影響,事務(wù)C正常插入。如果使用的是沒有索引的字段,比如update class_teacher set teacher_id=7 where class_name='初三八班(即使沒有匹配到任何數(shù)據(jù))',那么會給全表加入gap鎖。同時,它不能像上文中行鎖一樣經(jīng)過MySQL Server過濾自動解除不滿足條件的鎖,因為沒有索引,則這些字段也就沒有排序,也就沒有區(qū)間。除非該事務(wù)提交,否則其它事務(wù)無法插入任何數(shù)據(jù)。行鎖防止別的事務(wù)修改或刪除,GAP鎖防止別的事務(wù)新增,行鎖和GAP鎖結(jié)合形成的的Next-Key鎖共同解決了RR級別在寫數(shù)據(jù)時的幻讀問題。Serializable這個級別很簡單,讀加共享鎖,寫加排他鎖,讀寫互斥。使用的悲觀鎖的理論,實現(xiàn)簡單,數(shù)據(jù)更加安全,但是并發(fā)能力非常差。如果你的業(yè)務(wù)并發(fā)的特別少或者沒有并發(fā),同時又要求數(shù)據(jù)及時可靠的話,可以使用這種模式。這里要吐槽一句,不要看到select就說不會加鎖了,在Serializable這個級別,還是會加鎖的!

實現(xiàn)MySQL數(shù)據(jù)庫的備份與還原的幾種方法

MyISAM 表是保存成文件的形式,因此相對比較容易備份,上面提到的幾種方法都可以使用。Innodb 所有的表都保存在同一個數(shù)據(jù)文件 ibdata1 中(也可能是多個文件,或者是獨立的表空間文件),相對來說比較不好備份,免費的方案可以是拷貝數(shù)據(jù)文件、備份 binlog,或者用 mysqldump。1. 使用直接拷貝數(shù)據(jù)庫備份 典型的如cp、tar或cpio實用程序當(dāng)你使用直接備份方法時,必須保證表不在被使用。如果服務(wù)器在你正在拷貝一個表時改變它,拷貝就失去意義。保證你的拷貝完整性的最好方法是關(guān)閉服務(wù)器,拷貝文件,然后重啟服務(wù)器。 如果你不想關(guān)閉服務(wù)器,要在執(zhí)行表檢查的同時鎖定服務(wù)器。如果服務(wù)器在運行,相同的制約也適用于拷貝文件,應(yīng)該使用相同的鎖定協(xié)議讓服務(wù)器“安靜下來”。當(dāng)你完成了MySQL數(shù)據(jù)庫備份時,需要重啟服務(wù)器(如果關(guān)閉了它)或釋放加在表上的鎖定(如果你讓服務(wù)器運行)。 要用直接拷貝文件把一個數(shù)據(jù)庫從一臺機器拷貝到另一臺機器上,只是將文件拷貝到另一臺服務(wù)器主機的適當(dāng)數(shù)據(jù)目錄下即可。要確保文件是MyIASM格式或兩臺機器有相同的硬件結(jié)構(gòu),否則你的數(shù)據(jù)庫在另一臺主機上有奇怪的內(nèi)容。你也應(yīng)該保證在另一臺機器上的服務(wù)器在你正在安裝數(shù)據(jù)庫表時不訪問它們。2. 使用mysqldump數(shù)據(jù)庫備份mysqldump 是采用SQL級別的備份機制,它將數(shù)據(jù)表導(dǎo)成 SQL 腳本文件,在不同的 MySQL 版本之間升級時相對比較合適,這也是最常用的備份方法。mysqldump程序備份數(shù)據(jù)庫較慢,但它生成的文本文件便于移植。mysqldump 的一些主要參數(shù):1)--compatible=name它告訴 mysqldump,導(dǎo)出的數(shù)據(jù)將和哪種數(shù)據(jù)庫或哪個舊版本的 MySQL 服務(wù)器相兼容。值可以為 ansi、mysql323、mysql40、postgresql、oracle、mssql、db2、maxdb、no_key_options、no_tables_options、no_field_options 等,要使用幾個值,用逗號將它們隔開。當(dāng)然了,它并不保證能完全兼容,而是盡量兼容。2)--complete-insert,-c導(dǎo)出的數(shù)據(jù)采用包含字段名的完整 INSERT 方式,也就是把所有的值都寫在一行。這么做能提高插入效率,但是可能會受到 max_allowed_packet 參數(shù)的影響而導(dǎo)致插入失敗。因此,需要謹(jǐn)慎使用該參數(shù),至少我不推薦。3)--default-character-set=charset指定導(dǎo)出數(shù)據(jù)時采用何種字符集,如果數(shù)據(jù)表不是采用默認(rèn)的 latin1 字符集的話,那么導(dǎo)出時必須指定該選項,否則再次導(dǎo)入數(shù)據(jù)后將產(chǎn)生亂碼問題。4)--disable-keys告訴mysqldump 在 INSERT 語句的開頭和結(jié)尾增加 ; 和 ; 語句,這能大大提高插入語句的速度,因為它是在插入完所有數(shù)據(jù)后才重建索引的。該選項只適合 MyISAM 表。5)--extended-insert = true|false默認(rèn)情況下,mysqldump 開啟 --complete-insert 模式,因此不想用它的的話,就使用本選項,設(shè)定它的值為 false 即可。6)--hex-blob使用十六進(jìn)制格式導(dǎo)出二進(jìn)制字符串字段。如果有二進(jìn)制數(shù)據(jù)就必須使用本選項。影響到的字段類型有 BINARY、VARBINARY、BLOB。7)--lock-all-tables,-x在開始導(dǎo)出之前,提交請求鎖定所有數(shù)據(jù)庫中的所有表,以保證數(shù)據(jù)的一致性。這是一個全局讀鎖,并且自動關(guān)閉 --single-transaction 和 --lock-tables 選項。8)--lock-tables它和--lock-all-tables 類似,不過是鎖定當(dāng)前導(dǎo)出的數(shù)據(jù)表,而不是一下子鎖定全部庫下的表。本選項只適用于 MyISAM 表,如果是 Innodb 表可以用 --single-transaction 選項。9)--no-create-info,-t只導(dǎo)出數(shù)據(jù),而不添加 CREATE TABLE 語句。10)--no-data,-d不導(dǎo)出任何數(shù)據(jù),只導(dǎo)出數(shù)據(jù)庫表結(jié)構(gòu)。11)--opt這只是一個快捷選項,等同于同時添加 --add-drop-tables --add-locking --create-option --disable-keys --extended-insert --lock-tables --quick --set-charset 選項。本選項能讓 mysqldump 很快的導(dǎo)出數(shù)據(jù),并且導(dǎo)出的數(shù)據(jù)能很快導(dǎo)回。該選項默認(rèn)開啟,但可以用 --skip-opt 禁用。注意,如果運行 mysqldump 沒有指定 --quick 或 --opt 選項,則會將整個結(jié)果集放在內(nèi)存中。如果導(dǎo)出大數(shù)據(jù)庫的話可能會出現(xiàn)問題。12)--quick,-q該選項在導(dǎo)出大表時很有用,它強制 mysqldump 從服務(wù)器查詢?nèi)〉糜涗浿苯虞敵龆皇侨〉盟杏涗浐髮⑺鼈兙彺娴絻?nèi)存中。13)--routines,-R導(dǎo)出存儲過程以及自定義函數(shù)。14)--single-transaction該選項在導(dǎo)出數(shù)據(jù)之前提交一個 BEGIN SQL語句,BEGIN 不會阻塞任何應(yīng)用程序且能保證導(dǎo)出時數(shù)據(jù)庫的一致性狀態(tài)。它只適用于事務(wù)表,例如 InnoDB 和 BDB。 本選項和 --lock-tables 選項是互斥的,因為 LOCK TABLES 會使任何掛起的事務(wù)隱含提交。 要想導(dǎo)出大表的話,應(yīng)結(jié)合使用 --quick 選項。--triggers同時導(dǎo)出觸發(fā)器。該選項默認(rèn)啟用,用 --skip-triggers 禁用它。備份:使用mysqldump備份數(shù)據(jù)庫其實就是把數(shù)據(jù)庫轉(zhuǎn)儲成一系列CREATE TABLE和INSERT語句,通過這些語句我們就可重新生成數(shù)據(jù)庫。使用mysqldump的方法如下:% mysqldump --opt testdb | gzip /data/backup/testdb.bak#--opt選項會對轉(zhuǎn)儲過程進(jìn)行優(yōu)化,生成的備份文件會小一點,后的管道操作會進(jìn)行數(shù)據(jù)壓縮% mysqldump --opt testdb mytable1,mytable2 | gzip /data/backup/testdb_mytable.bak#可在數(shù)據(jù)庫后接數(shù)據(jù)表名,只導(dǎo)出指定的數(shù)據(jù)表,多個數(shù)據(jù)表可用逗號分隔--opt選項還可激活--add-drop-table選項,它將會在備份文件的每條CREATE TABLE前加上一條DROP TABLE IF EXISTS語句。這可方便進(jìn)行數(shù)據(jù)表的更新,而不會發(fā)生“數(shù)據(jù)表已存在”的錯誤。用mysqldump命令還可直接把數(shù)據(jù)庫轉(zhuǎn)移到另外一臺服務(wù)器上,不用生成備份文件。重復(fù)執(zhí)行可定期更新遠(yuǎn)程數(shù)據(jù)庫。% mysqladmin -h remote_host create testdb% mysqldump --opt testdb | mysql -h remote_host testdb另外還可通過ssh遠(yuǎn)程調(diào)用服務(wù)器上的程序,如:% ssh remote_host mysqladmin create testdb% mysqldump --opt testdb | ssh remote_host mysql testdb 通過直接拷貝系統(tǒng)文件的方式備份數(shù)據(jù)庫,在備份時,要確保沒有人對數(shù)據(jù)庫進(jìn)行修改操作。要做到這點,最好關(guān)閉服務(wù)器。如果不能關(guān)閉的,要以只讀方試鎖定有關(guān)數(shù)據(jù)表。下面是一些示例:% cp -r db /backup/db #備份db數(shù)據(jù)庫到/backup/db目錄% cp table_name.* /backup/db #只備份table_name數(shù)據(jù)表% scp -r db remotehot:/usr/local/mysql/data #用scp把數(shù)據(jù)庫直接拷貝到遠(yuǎn)程服務(wù)器,在把數(shù)據(jù)庫直接拷貝到遠(yuǎn)程主機時,應(yīng)注意兩臺機器必須有同樣的硬件結(jié)構(gòu),或者將拷貝的數(shù)據(jù)表全部是可移植數(shù)據(jù)表類型?;蛘?usr/local/mysql/bin/mysqldump -uroot -proot \--default-character-set=utf8 --opt --extended-insert=false \--triggers -R --hex-blob -x testdb testdb.sql使用以下 SQL 來備份 Innodb 表:/usr/local/mysql/bin/mysqldump -uroot -proot \--default-character-set=utf8 --opt --extended-insert=false \--triggers -R --hex-blob --single-transaction testdb testdb.sql另外,如果想要實現(xiàn)在線備份,還可以使用 --master-data 參數(shù)來實現(xiàn),如下:/usr/local/mysql/bin/mysqldump -uroot -proot \--default-character-set=utf8 --opt --master-data=1 \--single-transaction --flush-logs testdb testdb.sql它只是在一開始的瞬間請求鎖表,然后就刷新binlog了,而后在導(dǎo)出的文件中加入CHANGE MASTER 語句來指定當(dāng)前備份的binlog位置,如果要把這個文件恢復(fù)到slave里去,就可以采用這種方法來做。 還原:用mysqldump 備份出來的文件是一個可以直接倒入的 SQL 腳本,有兩種方法可以將數(shù)據(jù)導(dǎo)入。直接用 mysql 客戶端例如:/usr/local/mysql/bin/mysql -uroot -proot testdb testdb.sql用SOURCE 語法其實這不是標(biāo)準(zhǔn)的 SQL 語法,而是 mysql 客戶端提供的功能,例如:SOURCE /tmp/testdb.sql;這里需要指定文件的絕對路徑,并且必須是 mysqld 運行用戶(例如 nobody)有權(quán)限讀取的文件。 3. 使用mysqlhotcopy數(shù)據(jù)庫備份 使用mysqlhotcopy工具,它是一個Perl DBI腳本,可在不關(guān)閉服務(wù)器的情況下備份數(shù)據(jù)庫,mysqlhotcopy 是一個 PERL 程序,最初由Tim Bunce編寫。它使用 LOCK TABLES、FLUSH TABLES 和 cp 或 scp 來快速備份數(shù)據(jù)庫。它是備份數(shù)據(jù)庫或單個表的最快的途徑,但它只能運行在數(shù)據(jù)庫文件(包括數(shù)據(jù)表定義文件、數(shù)據(jù)文件、索引文件)所在的機器上。mysqlhotcopy 只能用于備份 MyISAM,并且只能運行在 類Unix 和 NetWare 系統(tǒng)上。它主要的優(yōu)點是:它直接拷貝文件,所以它比mysqldump快??勺詣油瓿蓴?shù)據(jù)鎖定工作,備份時不用關(guān)閉服務(wù)器。能刷新日志,使備份文件和日志文件的檢查點能保持同步。備份:mysqlhotcopy 支持一次性拷貝多個數(shù)據(jù)庫,同時還支持正則表達(dá)。以下是幾個例子:/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=root -p=root \testdb /tmp (把數(shù)據(jù)庫目錄 testdb 拷貝到 /tmp 下)/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=root -p=root \testdb_1 testdb_2 testdb_n /tmp/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=root -p=root \testdb./regex/ /tmp 還原:mysqlhotcopy 備份出來的是整個數(shù)據(jù)庫目錄,使用時可以直接拷貝到 mysqld 指定的 datadir (在這里是 /usr/local/mysql/data/)目錄下即可,同時要注意權(quán)限的問題,如下例:cp -rf testdb /usr/local/mysql/data/chown -R nobody:nobody /usr/local/mysql/data/ (將 testdb 目錄的屬主改成 mysqld 運行用戶) 4. 使用SQL語句數(shù)據(jù)庫備份 BACKUP TABLE 語法其實和 mysqlhotcopy 的工作原理差不多,都是鎖表,然后拷貝數(shù)據(jù)文件。它能實現(xiàn)在線備份,但是效果不理想,因此不推薦使用。它只拷貝表結(jié)構(gòu)文件和數(shù)據(jù)文件,不同時拷貝索引文件,因此恢復(fù)時比較慢。備份:BACK TABLE tbl_test TO '/tmp/testdb/'; #把tbl_test數(shù)據(jù)庫備份到/tmp/testdb/目錄里,會自動創(chuàng)建一個testdb目錄 為了執(zhí)行該語句,你必須擁有那些表的FILE權(quán)限和SELECT權(quán)限,備份目錄還必須是服務(wù)器可寫的。該語句執(zhí)行時,會先把內(nèi)存中的數(shù)據(jù)寫入磁盤,再把各個數(shù)據(jù)表的.frm(表結(jié)構(gòu)定義文件)、.MYD(數(shù)據(jù))文件從數(shù)據(jù)目錄拷貝到備份目錄。它不拷貝.MYI(索引)文件,因為它能用另外兩個文件重建。BACKUP TABLE語句備份時,依次鎖定數(shù)據(jù)表,當(dāng)同時備份多個數(shù)據(jù)表時,數(shù)據(jù)表可能會被修改,所以備份0完成時,備份文件中的數(shù)據(jù)和現(xiàn)時數(shù)據(jù)表中的數(shù)據(jù)可能會有差異,為了消除該差異,我們可用只讀方式鎖定數(shù)據(jù)表,在備份完成后再解鎖。如:mysql LOCK TABLES tb1 READ,tb2 READ;mysql BACKUP TABLE tb1,tb2 TO 'backup/db';mysql UNLOCK TABLES;使用BACKUP TABLE語句備份的數(shù)據(jù)表可用RESTORE TABLE重新加載到服務(wù)器。注意,必須要有 FILE 權(quán)限才能執(zhí)行本SQL,并且目錄 /tmp/testdb/ 必須能被 mysqld 用戶可寫,導(dǎo)出的文件不能覆蓋已經(jīng)存在的文件,以避免安全問題。SELECT INTO OUTFILE 則是把數(shù)據(jù)導(dǎo)出來成為普通的文本文件,可以自定義字段間隔的方式,方便處理這些數(shù)據(jù)。 例子:SELECT * INTO OUTFILE '/tmp/testdb/tbl_test.txt' FROM tbl_test;注意,必須要有 FILE 權(quán)限才能執(zhí)行本SQL,并且文件 /tmp/testdb/tbl_test.txt 必須能被 mysqld 用戶可寫,導(dǎo)出的文件不能覆蓋已經(jīng)存在的文件,以避免安全問題。還原:用BACKUP TABLE 方法備份出來的文件,可以運行 RESTORE TABLE 語句來恢復(fù)數(shù)據(jù)表。例子:RESTORE TABLE FROM '/tmp/testdb/';權(quán)限要求類似上面所述。用SELECT INTO OUTFILE 方法備份出來的文件,可以運行 LOAD DATA INFILE 語句來恢復(fù)數(shù)據(jù)表。例子:LOAD DATA INFILE '/tmp/testdb/tbl_name.txt' INTO TABLE tbl_name;權(quán)限要求類似上面所述。倒入數(shù)據(jù)之前,數(shù)據(jù)表要已經(jīng)存在才行。

文章標(biāo)題:包含postgresql解鎖的詞條
文章轉(zhuǎn)載:http://jinyejixie.com/article8/dsdggip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)ChatGPT、微信公眾號網(wǎng)站制作、動態(tài)網(wǎng)站、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)
岱山县| 云梦县| 治县。| 荔浦县| 鹤庆县| 江华| 图们市| 南溪县| 宿松县| 阳信县| 耿马| 三穗县| 东乡县| 错那县| 铜鼓县| 黄大仙区| 鲁甸县| 汪清县| 常宁市| 麻江县| 海晏县| 本溪| 常山县| 绥棱县| 威宁| 西乌珠穆沁旗| 子洲县| 澳门| 静海县| 锡林郭勒盟| 鹿邑县| 莱州市| 会昌县| 海门市| 彰化市| 扎囊县| 揭东县| 镶黄旗| 汶川县| 曲阳县| 宜宾县|