日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

讨论MySQL丢失数据的几种情况

發(fā)布時(shí)間:2024/4/14 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 讨论MySQL丢失数据的几种情况 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 問(wèn)題定義

一般我們希望把一系列的數(shù)據(jù)作為一個(gè)原子操作,這樣的話,這一系列操作,要么提交,要么全部回滾掉。

????當(dāng)我們提交一個(gè)事務(wù),數(shù)據(jù)庫(kù)要么告訴我們事務(wù)提交成功了,要么告訴我們提交失敗。

  數(shù)據(jù)庫(kù)為了效率等原因,數(shù)據(jù)只保存在內(nèi)存中,沒(méi)有真正的寫入到磁盤上去。如果數(shù)據(jù)庫(kù)響應(yīng)為“提交成功”,但是由于數(shù)據(jù)庫(kù)掛掉,操作系統(tǒng),數(shù)據(jù)庫(kù)主機(jī)等任何問(wèn)題導(dǎo)致這次“提交成功”的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改沒(méi)有生效,那么我們認(rèn)為這個(gè)事務(wù)的數(shù)據(jù)丟失了。這個(gè)對(duì)銀行或者支付寶這種業(yè)務(wù)場(chǎng)景來(lái)說(shuō)是不能接受的。所以,保證數(shù)據(jù)不丟失也是數(shù)據(jù)庫(kù)選擇的一個(gè)重要衡量指標(biāo)

  mysql的架構(gòu)和普通的數(shù)據(jù)庫(kù)架構(gòu)最大的差異在于它使用插件式的存儲(chǔ)引擎。數(shù)據(jù)的存取由存儲(chǔ)引擎負(fù)責(zé)。要了解MySQL數(shù)據(jù)丟失的問(wèn)題就需要從MySQL server層和InnoDB目前最流行的支持事務(wù)的存儲(chǔ)引擎分別來(lái)分析了。

2. INNODB事務(wù)數(shù)據(jù)丟失

首先,我們來(lái)看一下InnoDB事務(wù)數(shù)據(jù)丟失的情況。

2.1. INNODB事務(wù)基本原理

InnoDB的事務(wù)提交需要寫入undo log,redo log,以及真正的數(shù)據(jù)頁(yè)。InnoDB跟Oracle非常類似,使用日志先行的策略,將數(shù)據(jù)的變更在內(nèi)存中完成,并且將事務(wù)記錄成redo,轉(zhuǎn)換為順序IO高效的提交事務(wù)。這里日志先行,也就是說(shuō),日志記錄到數(shù)據(jù)庫(kù)以后,對(duì)應(yīng)的事務(wù)就可以返回給用戶,表示事務(wù)完成。但是實(shí)際上,這個(gè)數(shù)據(jù)可能還只在內(nèi)存中修改完成,并沒(méi)有刷到磁盤上去,俗稱“還沒(méi)有落地”。內(nèi)存是易失的,如果在數(shù)據(jù)“落地”之前,機(jī)器掛了,那么這部分?jǐn)?shù)據(jù)就丟失了。而數(shù)據(jù)庫(kù)怎么保證這些數(shù)據(jù)還是能夠找回來(lái)列?否則,用戶提交了一個(gè)事務(wù),數(shù)據(jù)庫(kù)響應(yīng)請(qǐng)求并回應(yīng)為事務(wù)“提交成功”,數(shù)據(jù)庫(kù)重啟以后,這部分修改數(shù)據(jù)的卻回到了事務(wù)提交之前的狀態(tài)。

2.2. INNODB事務(wù)崩潰恢復(fù)基本原理

InnoDB和Oracle都是利用redo來(lái)保證數(shù)據(jù)一致性的。如果你有從數(shù)據(jù)庫(kù)新建一直到數(shù)據(jù)庫(kù)掛掉的所有redo,那么你可以將數(shù)據(jù)完完整整的重新build出來(lái)。但是這樣的話,速度肯定很慢。所以一般每隔一段時(shí)間,數(shù)據(jù)庫(kù)會(huì)做一個(gè)checkpoint的操作,做checkpoint的目的就是為了讓在該時(shí)刻之前的所有數(shù)據(jù)都"落地"。這樣的話,數(shù)據(jù)庫(kù)掛了,內(nèi)存中的數(shù)據(jù)丟了,不用從最原始的位置開始恢復(fù),而只需要從最新的checkpoint來(lái)恢復(fù)。將已經(jīng)提交的所有事務(wù)變更到具體的數(shù)據(jù)塊中,將那些未提交的事務(wù)回滾掉。

2.3. INNODB REDO日志

這樣的話,保證事務(wù)的redo日志刷到磁盤就成了事務(wù)數(shù)據(jù)是否丟失的關(guān)鍵。而InnoDB為了保證日志的刷寫的高效,使用了內(nèi)存的log buffer,另外,由于InnoDB大部分情況下使用的是文件系統(tǒng),(linux文件系統(tǒng)本身也是有buffer的)而不是直接使用物理塊設(shè)備,這樣的話就有兩種丟失日志的可能性:日志保存在log_buffer中,機(jī)器掛了,對(duì)應(yīng)的事務(wù)數(shù)據(jù)就丟失了;日志從log buffer刷到了linux文件系統(tǒng)的buffer,機(jī)器掛掉了,對(duì)應(yīng)的事務(wù)數(shù)據(jù)就丟失了。當(dāng)然,文件系統(tǒng)的緩存刷新到硬件設(shè)備,還有可能被raid卡的緩存,甚至是磁盤本身的緩存保留,而不是真正的寫到磁盤介質(zhì)上去了。

2.4. INNODB_FLUSH_LOG_AT_TRX_COMMIT

所以InnoDB有一個(gè)特別的參數(shù)用于設(shè)置這兩個(gè)緩存的刷新: innodb_flush_log_at_trx_commit。

  默認(rèn),innodb_flush_log_at_trx_commit=1,表示在每次事務(wù)提交的時(shí)候,都把log buffer刷到文件系統(tǒng)中去,并且調(diào)用文件系統(tǒng)的“flush”操作將緩存刷新到磁盤上去。這樣的話,數(shù)據(jù)庫(kù)對(duì)IO的要求就非常高了,如果底層的硬件提供的IOPS比較差,那么MySQL數(shù)據(jù)庫(kù)的并發(fā)很快就會(huì)由于硬件IO的問(wèn)題而無(wú)法提升。

  為了提高效率,保證并發(fā),犧牲一定的數(shù)據(jù)一致性。innodb_flush_log_at_trx_commit還可以設(shè)置為0和2。

  innodb_flush_log_at_trx_commit=0時(shí),每隔一秒把log buffer刷到文件系統(tǒng)中去,并且調(diào)用文件系統(tǒng)的“flush”操作將緩存刷新到磁盤上去。這樣的話,可能丟失1秒的事務(wù)數(shù)據(jù)。

  innodb_flush_log_at_trx_commit=2時(shí),在每次事務(wù)提交的時(shí)候會(huì)把log buffer刷到文件系統(tǒng)中去,但是每隔一秒調(diào)用文件系統(tǒng)的“flush”操作將緩存刷新到磁盤上去。如果只是MySQL數(shù)據(jù)庫(kù)掛掉了,由于文件系統(tǒng)沒(méi)有問(wèn)題,那么對(duì)應(yīng)的事務(wù)數(shù)據(jù)并沒(méi)有丟失。只有在數(shù)據(jù)庫(kù)所在的主機(jī)操作系統(tǒng)損壞或者突然掉電的情況下,數(shù)據(jù)庫(kù)的事務(wù)數(shù)據(jù)可能丟失1秒之類的事務(wù)數(shù)據(jù)。這樣的好處就是,減少了事務(wù)數(shù)據(jù)丟失的概率,而對(duì)底層硬件的IO要求也沒(méi)有那么高(log buffer寫到文件系統(tǒng)中,一般只是從log buffer的內(nèi)存轉(zhuǎn)移的文件系統(tǒng)的內(nèi)存緩存中,對(duì)底層IO沒(méi)有壓力)。MySQL 5.6.6以后,這個(gè)“1秒”的刷新還可以用innodb_flush_log_at_timeout 來(lái)控制刷新間隔。

  在大部分應(yīng)用環(huán)境中,應(yīng)用對(duì)數(shù)據(jù)的一致性要求并沒(méi)有那么高,所以很多MySQL DBA會(huì)設(shè)置innodb_flush_log_at_trx_commit=2,這樣的話,數(shù)據(jù)庫(kù)就存在丟失最多1秒的事務(wù)數(shù)據(jù)的風(fēng)險(xiǎn)。

如下圖所示:


3. 數(shù)據(jù)庫(kù)復(fù)制導(dǎo)致數(shù)據(jù)丟失

MySQL相比其他數(shù)據(jù)庫(kù)更適用于互聯(lián)網(wǎng)的其中一個(gè)重要特性就是MySQL的復(fù)制。對(duì)于互聯(lián)網(wǎng)這種需要提供7*24小時(shí)不間斷的服務(wù)的要求,MySQL提供異步的數(shù)據(jù)同步機(jī)制。利用這種復(fù)制同步機(jī)制,當(dāng)數(shù)據(jù)庫(kù)主庫(kù)無(wú)法提供服務(wù)時(shí),應(yīng)用可以快速切換到跟它保持同步的一個(gè)備庫(kù)中去。備庫(kù)繼續(xù)為應(yīng)用提供服務(wù),從而不影響應(yīng)用的可用性。

  這里有一個(gè)關(guān)鍵的問(wèn)題,就是應(yīng)用切換到備庫(kù)訪問(wèn),備庫(kù)的數(shù)據(jù)需要跟主庫(kù)的數(shù)據(jù)一致才能保證不丟失數(shù)據(jù)。由于目前MySQL還沒(méi)有提供全同步的主備復(fù)制解決方案所以這里也是可能存在數(shù)據(jù)丟失的情況。

  目前MySQL提供兩種主備同步的方式:異步(asynchronous)和半同步(Semi-sync)

3.1. MYSQL復(fù)制原理簡(jiǎn)介

MySQL復(fù)制的原理簡(jiǎn)介如下:MySQL主庫(kù)在事務(wù)提交時(shí)寫binlog,并通過(guò)sync_binlog參數(shù)來(lái)控制binlog刷新到磁盤“落地”。而備庫(kù)通過(guò)IO線程從主庫(kù)拉取binlog,并記錄到本地的relay log中;由本地的SQL線程再將relay log中的數(shù)據(jù)應(yīng)用到本地?cái)?shù)據(jù)庫(kù)中。

異步的方式下,幾個(gè)線程都是獨(dú)立的,相互不依賴。

而在半同步的情況下,主庫(kù)的事務(wù)提交需要保證至少有一個(gè)備庫(kù)的IO線程已經(jīng)拉到了數(shù)據(jù),這樣保證了至少有一個(gè)備庫(kù)有最新的事務(wù)數(shù)據(jù),避免了數(shù)據(jù)丟失。這里稱為半同步,是因?yàn)橹鲙?kù)并不要求SQL線程已經(jīng)執(zhí)行完成了這個(gè)事務(wù)。

半同步在MySQL 5.5才開始提供,并且可能引起并發(fā)和效率的一系列問(wèn)題,比如只有一個(gè)備庫(kù),備庫(kù)掛掉了,那么主庫(kù)在事務(wù)提交10秒(rpl_semi_sync_master_timeout控制)后,才會(huì)繼續(xù),之后變成傳統(tǒng)的異步方式。所以目前在生產(chǎn)環(huán)境下使用半同步的比較少。

在異步方式下,如何保證數(shù)據(jù)盡量不丟失就成了主要問(wèn)題。這個(gè)問(wèn)題其實(shí)就是如何保證數(shù)據(jù)庫(kù)的binlog不丟失,盡快將binlog落地,這樣就算數(shù)據(jù)庫(kù)掛掉了,我們還可以通過(guò)binlog來(lái)將丟失的部分?jǐn)?shù)據(jù)手工同步到備庫(kù)上去(MHA會(huì)自動(dòng)抽取缺失的部分補(bǔ)全備庫(kù))。

3.2. SYNC_BINLOG

這個(gè)問(wèn)題就跟上一個(gè)innodb_flush_log_at_trx_commit的問(wèn)題類似了。MySQL提供一個(gè)sync_binlog參數(shù)來(lái)控制數(shù)據(jù)庫(kù)的binlog刷到磁盤上去。雖然binlog也有binlog cache,但是MySQL并沒(méi)有控制binlog cache同步到文件系統(tǒng)緩存的相關(guān)考慮。所以我們這里不涉及binlog cache。

  默認(rèn),sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系統(tǒng)自己控制它的緩存的刷新。

  如果sync_binlog>0,表示每sync_binlog次事務(wù)提交,MySQL調(diào)用文件系統(tǒng)的刷新操作將緩存刷下去。最安全的就是sync_binlog=1了,表示每次事務(wù)提交,MySQL都會(huì)把binlog刷下去。這樣的話,在數(shù)據(jù)庫(kù)所在的主機(jī)操作系統(tǒng)損壞或者突然掉電的情況下,系統(tǒng)才有可能丟失1個(gè)事務(wù)的數(shù)據(jù)。但是binlog雖然是順序IO,但是設(shè)置sync_binlog=1,多個(gè)事務(wù)同時(shí)提交,同樣很大的影響MySQL和IO性能。雖然可以通過(guò)group commit的補(bǔ)丁緩解,但是刷新的頻率過(guò)高對(duì)IO的影響也非常大。

  所以很多MySQL DBA設(shè)置的sync_binlog并不是最安全的1,而是100或者是0。這樣犧牲一定的一致性,可以獲得更高的并發(fā)和性能。

4. MYSQL和INNODB協(xié)同

4.1. 兩段式事務(wù)提交

最后我們需要討論一下上述兩個(gè)參數(shù)對(duì)應(yīng)的redolog和 binlog協(xié)同的問(wèn)題。這兩個(gè)log都影響數(shù)據(jù)丟失,但是他們分別在InnoDB和MySQL server層維護(hù)。由于一個(gè)事務(wù)可能使用兩種事務(wù)引擎,所以MySQL用兩段式事務(wù)提交來(lái)協(xié)調(diào)事務(wù)提交。我們先簡(jiǎn)單了解一下兩段式事務(wù)提交的過(guò)程.

第一階段:

  首先,協(xié)調(diào)者在自身節(jié)點(diǎn)的日志中寫入一條的日志記錄,然后所有參與者發(fā)送消息prepare T,詢問(wèn)這些參與者(包括自身),是否能夠提交這個(gè)事務(wù);

  參與者在接受到這個(gè)prepare T 消息以后,會(huì)根據(jù)自身的情況,進(jìn)行事務(wù)的預(yù)處理,如果參與者能夠提交該事務(wù),則會(huì)將日志寫入磁盤,并返回給協(xié)調(diào)者一個(gè)ready T信息,同時(shí)自身進(jìn)入預(yù)提交狀態(tài)狀態(tài);如果不能提交該事務(wù),則記錄日志,并返回一個(gè)not commit T信息給協(xié)調(diào)者,同時(shí)撤銷在自身上所做的數(shù)據(jù)庫(kù)改;

  參與者能夠推遲發(fā)送響應(yīng)的時(shí)間,但最終還是需要發(fā)送的。

第二階段:

  協(xié)調(diào)者會(huì)收集所有參與者的意見,如果收到參與者發(fā)來(lái)的not commit T信息,則標(biāo)識(shí)著該事務(wù)不能提交,協(xié)調(diào)者會(huì)將Abort T 記錄到日志中,并向所有參與者發(fā)送一個(gè)Abort T 信息,讓所有參與者撤銷在自身上所有的預(yù)操作;

  如果協(xié)調(diào)者收到所有參與者發(fā)來(lái)prepare T信息,那么協(xié)調(diào)者會(huì)將Commit T日志寫入磁盤,并向所有參與者發(fā)送一個(gè)Commit T信息,提交該事務(wù)。若協(xié)調(diào)者遲遲未收到某個(gè)參與者發(fā)來(lái)的信息,則認(rèn)為該參與者發(fā)送了一個(gè)VOTE_ABORT信息,從而取消該事務(wù)的執(zhí)行。

  參與者接收到協(xié)調(diào)者發(fā)來(lái)的Abort T信息以后,參與者會(huì)終止提交,并將Abort T 記錄到日志中;如果參與者收到的是Commit T信息,則會(huì)將事務(wù)進(jìn)行提交,并寫入記錄

  一般情況下,兩階段提交機(jī)制都能較好的運(yùn)行,當(dāng)在事務(wù)進(jìn)行過(guò)程中,有參與者宕機(jī)時(shí),他重啟以后,可以通過(guò)詢問(wèn)其他參與者或者協(xié)調(diào)者,從而知道這個(gè)事務(wù)到底提交了沒(méi)有。當(dāng)然,這一切的前提都是各個(gè)參與者在進(jìn)行每一步操作時(shí),都會(huì)事先寫入日志。

4.2. INNODB_SUPPORT_XA

  innodb_support_xa可以開關(guān)InnoDB的xa兩段式事務(wù)提交。默認(rèn)情況下,innodb_support_xa=true,支持xa兩段式事務(wù)提交。此時(shí)MySQL首先要求innodb prepare,對(duì)應(yīng)的redolog 將寫入log buffer;如果有其他的引擎,其他引擎也需要做事務(wù)提交的prepare,然后MySQL server將binlog將寫入;并通知各事務(wù)引擎真正commit;InnoDB將commit標(biāo)志寫入,完成真正的提交,響應(yīng)應(yīng)用程序?yàn)樘峤怀晒Α_@個(gè)過(guò)程中任何出錯(cuò)將導(dǎo)致事務(wù)回滾,響應(yīng)應(yīng)用程序?yàn)樘峤皇 R簿褪钦f(shuō),在這種情況下,基本不會(huì)出錯(cuò)。

  但是由于xa兩段式事務(wù)提交導(dǎo)致多余flush等操作,性能影響會(huì)達(dá)到10%,所有為了提高性能,有些DBA會(huì)設(shè)置innodb_support_xa=false。這樣的話,redolog和binlog將無(wú)法同步,可能存在事務(wù)在主庫(kù)提交,但是沒(méi)有記錄到binlog的情況。這樣也有可能造成事務(wù)數(shù)據(jù)的丟失。

  綜上,我們列舉了影響InnoDB數(shù)據(jù)丟失的參數(shù)innodb_flush_log_at_trx_commit,影響MySQL復(fù)制數(shù)據(jù)丟失的sync_binlog,以及由于MySQL和InnoDB需要協(xié)調(diào)而可能導(dǎo)致數(shù)據(jù)丟失的參數(shù)innodb_support_xa。

轉(zhuǎn)載于:https://blog.51cto.com/xiaoze/1607601

總結(jié)

以上是生活随笔為你收集整理的讨论MySQL丢失数据的几种情况的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。