網(wǎng)上有很多關(guān)于pos機(jī)交易日志已滿請先結(jié)算,mysql總結(jié)筆記的知識,也有很多人為大家解答關(guān)于pos機(jī)交易日志已滿請先結(jié)算的問題,今天pos機(jī)之家(m.shineka.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!
本文目錄一覽:
pos機(jī)交易日志已滿請先結(jié)算
1 一條SQL查詢語句是如何執(zhí)行的?
mysql邏輯處理架構(gòu):4層 (連接,服務(wù),引擎,存儲)
主要:Server層和引擎層
1.1 服務(wù)層
連接器:管理連接,權(quán)限驗(yàn)證
如果用戶名密碼認(rèn)證通過,連接器會到權(quán)限表里面查出你擁有的權(quán)限。之后,這個(gè)連接里面的權(quán)限判斷邏輯,都將依賴于此時(shí)讀到的權(quán)限。查看連接:show processlist ,Command 列顯示為“Sleep”的這一行,就表示現(xiàn)在系統(tǒng)里面有一個(gè)空閑連接??蛻舳巳绻L時(shí)間沒動(dòng)靜,連接器就會自動(dòng)將它斷開。這個(gè)時(shí)間是由參數(shù) wait_timeout 控制的,默認(rèn)值是 8 小時(shí)。mysql執(zhí)行過程中使用的內(nèi)存是管理在連接對象里,所以長連接累積下來,可能導(dǎo)致內(nèi)存占用太大,被系統(tǒng)強(qiáng)行殺掉(OOM),從現(xiàn)象看就是 MySQL 異常重啟了。
解決辦法:
1,定期斷開長連接。使用一段時(shí)間,或者程序里面判斷執(zhí)行過一個(gè)占用內(nèi)存的大查詢后,斷開連接,之后要查詢再重連。
2,如果你用的是 MySQL 5.7 或更新版本,可以在每次執(zhí)行一個(gè)比較大的操作后,通過執(zhí)行 mysql_reset_connection 來重新初始化連接資源。
查詢緩存:mysql8已棄用
執(zhí)行一個(gè)查詢請求,先從緩存中查找,沒有再到數(shù)據(jù)庫查。
不建議使用查詢緩存,因?yàn)榫彺媸鞘Х浅nl繁。我們會對表做更新,只要有更新,緩存就失效。而且查詢緩存的命中率很低。
配置: query_CACHE_type 設(shè)置成 DEMAND,這樣對于默認(rèn)的 SQL 語句都不使用查詢緩存。用 SQL_CACHE 顯式指定,select SQL_CACHE * from T where ID=10;
分析器:先詞法分析,后語法分析。詞法分析主要做的是根據(jù)mysql的關(guān)鍵字進(jìn)行驗(yàn)證和解析,而語法分析會在詞法解析的基礎(chǔ)上進(jìn)一步做表名和字段名稱的驗(yàn)證和解析;
優(yōu)化器:優(yōu)化sql,執(zhí)行計(jì)劃生成,選擇索引
選擇索引,選擇表的連接順序。
執(zhí)行器:操作引擎,返回結(jié)果
先判斷有沒有表執(zhí)行權(quán)限,有才往下執(zhí)行。根據(jù)表的定義,選擇引擎。
1.2 引擎層
讀取存儲層(文件)數(shù)據(jù)
小結(jié):建立連接,先重緩存中找,沒有找到。則依次執(zhí)行-分析器,優(yōu)化器,執(zhí)行器。執(zhí)行前先做權(quán)限檢查,最后調(diào)用引擎層接口返回?cái)?shù)據(jù)。
2 一條SQL更新語句是如何執(zhí)行的?
create table T(ID int primary key, c int);
update T set c=c+1 where ID=2;
1, 更新語句也要經(jīng)過,連接器,分析器,優(yōu)化器,執(zhí)行器,調(diào)用引擎更新數(shù)據(jù)。
2,執(zhí)行器執(zhí)行過程:
(1)根據(jù)優(yōu)化器結(jié)果,找到主鍵索引樹查找,找到id=2 這一行,如何id=2這一行的數(shù)據(jù)頁在內(nèi)存中,就直接返回給執(zhí)行器,否則先從磁盤讀入內(nèi)存。
(2)執(zhí)行器得到引擎接口給到行數(shù)據(jù),把c 加上1 。得到新的一行數(shù)據(jù),再調(diào)用引擎接口寫入。
(3)引擎開啟事務(wù),將這行數(shù)據(jù)更新到內(nèi)存中,同時(shí)也寫入到redo log中,此時(shí)redo log處于prepare狀態(tài),告訴執(zhí)行器執(zhí)行完成了。
(4)執(zhí)行器生成這個(gè)操作的binlog日志,寫入磁盤
(5)執(zhí)行器調(diào)用引擎的事務(wù)提交接口,把剛寫入的redo log 改成commit 狀態(tài),更新完成。
這個(gè) update 語句的執(zhí)行流程圖,圖中淺色框表示是在 InnoDB 內(nèi)部執(zhí)行的,深色框表示是在執(zhí)行器中執(zhí)行的。
其中涉及到兩階段提交,目的是保證binlog和redo log數(shù)據(jù)一致性。否則,通過binlog恢復(fù)數(shù)據(jù),或者擴(kuò)容,就會出現(xiàn)問題。
2.1 redo log (重做日志)
redo log 日志其實(shí)也是寫io放在磁盤,但是是順序?qū)?,有?yōu)化,效率高。
redo log 獨(dú)屬于innodb引擎,默認(rèn)一組4個(gè)文件,每個(gè)文件大小為1GB. 數(shù)據(jù)結(jié)構(gòu):循環(huán)隊(duì)列,類比ringBuffer。 循環(huán)寫,空間會用完。用完后會刷盤。
redo log 是物理日志,只有innodb引擎可以使用的格式,記錄的是“某個(gè)數(shù)據(jù)頁做了什么修改”。
crash-safe: 有了 redo log,InnoDB 就可以保證即使數(shù)據(jù)庫發(fā)生異常重啟,之前提交的記錄都不會丟失。重啟后,自動(dòng)讀取redo log ,恢復(fù)數(shù)據(jù)。
類比:《孔乙己》,餐館掌柜記賬,粉板(redo log , 內(nèi)存), 賬本 (磁盤)。當(dāng)有一條記錄需要更新的時(shí)候,InnoDB 引擎就會先把記錄寫到 redo log(粉板)里面,并更新內(nèi)存,當(dāng)有一條記錄需要更新的時(shí)候,InnoDB 引擎就會先把記錄寫到 redo log(粉板)里面,并更新內(nèi)存,
WAL 的全稱是 Write-Ahead Logging,它的關(guān)鍵點(diǎn)就是先寫日志,再寫磁盤,也就是先寫粉板,等不忙的時(shí)候再寫賬本。
redo log的寫入包括兩部分內(nèi)容:一部分是內(nèi)存中的日志緩沖,稱作redo log buffer;另一部分是磁盤日志文件,稱作 redo log file。MySQL每執(zhí)行一條DML語句,先將更新記錄寫入redo log buffer ,然后再寫入redo log file。我們將這種先寫日志,再寫磁盤的方式稱為 WAL(Write-Ahead Logging)技術(shù)。
redo log buffer寫入redo log file的時(shí)機(jī),可以通過 參數(shù)innodb_flush_log_at_trx_commit 進(jìn)行配置,innodb_flush_log_at_trx_commit 這個(gè)參數(shù)設(shè)置成 1 的時(shí)候,表示每次事務(wù)的 redo log 都直接持久化到磁盤。建議你設(shè)置成 1,這樣可以保證 MySQL 異常重啟之后數(shù)據(jù)不丟失。
參數(shù)為0的時(shí)候,稱為“延遲寫”。事務(wù)提交時(shí)不會將redo log buffer中日志寫入到OS buffer,而是每秒寫入OS buffer并調(diào)用寫入到redo log file中。換句話說,1秒后,實(shí)時(shí)寫和實(shí)時(shí)刷,只會丟失1秒鐘的數(shù)據(jù)。參數(shù)為1 的時(shí)候,稱為“實(shí)時(shí)寫,實(shí)時(shí)刷”。事務(wù)每次提交都會將redo log buffer中的日志寫入OS buffer并保存到redo log file中。其有點(diǎn)是,即使系統(tǒng)崩潰也不會丟失任何數(shù)據(jù),缺點(diǎn)也很明顯就是每次事務(wù)提交都要進(jìn)行磁盤操作,性能較差。參數(shù)為2的時(shí)候,稱為“實(shí)時(shí)寫,延遲刷”。每次事務(wù)提交寫入到OS buffer,然后是每秒將日志寫入到redo log file。這樣性能會好點(diǎn),缺點(diǎn)是在系統(tǒng)崩潰的時(shí)候會丟失1秒中的事務(wù)數(shù)據(jù)。每秒刷一次。這個(gè)刷日志的頻率由變量 innodb_flush_log_at_timeout 值決定,默認(rèn)是1秒。要注意,這個(gè)刷日志頻率和commit動(dòng)作無關(guān)。
redo log記錄的是數(shù)據(jù)頁的物理變化,恢復(fù)的速度比邏輯日志(binlog)要快。
show GLOBAL VARIABLES like 'innodb_log%'
redo log 磁盤日志文件的總大?。?strong>innodb_log_file_size* innodb_log_files_in_group)
2.2 binlog(歸檔日志)
binlog 屬于server層,所有引擎都可以用。追加寫,文件寫到一定大小后會切換到下一個(gè),并不會覆蓋以前的日志。
binlog 是物理日志,記錄的是原始邏輯,比如sql語句。
Binlog有3種模式,STATEMENT 格式的話是記sql語句, row格式會記錄行的內(nèi)容,記兩條,更新前和更新后都有。mixed 混合模式,默認(rèn)使用STATEMENT模式保存,STATEMENT模式無法復(fù)制的操作使用ROW模式。
# 設(shè)置格式
set binlog_format = 'STATEMENT’;
# 關(guān)閉binlog
set sql_log_bin=0;
sync_binlog 這個(gè)參數(shù)設(shè)置成 1 的時(shí)候,表示每次事務(wù)的 binlog 都持久化到磁盤。建議你設(shè)置成 1,這樣可以保證 MySQL 異常重啟之后 binlog 不丟失
查看binlog日志列表:show master logs;
生成一個(gè)新的binlog日志:FLUSH BINARY LOGS;
查看最后一個(gè)binlog日志:show master status;
查看binlog日志的事件:show binlog events ;show binlog events in 'mysql-bin.001333’;
指定查詢,從pos點(diǎn)406開始查詢:show binlog events in 'mysql-bin.001333’ from 406;
lLog_name:描述存放binlog日志的文件名字。
lPos:描述記日志的開始位置。
lEvent_type:描述類型,例如:查詢、插入等。
lServer_id:對應(yīng)數(shù)據(jù)庫服務(wù)器的ID。
lEnd_log_pos:日志結(jié)束的位置。
lInfo:執(zhí)行的SQL語句。
使用mysqlbinlog 命令查看
常用選項(xiàng):
--start-position=953 起始pos點(diǎn)
--stop-position=1437 結(jié)束pos點(diǎn)
--start-datetime="2013-11-29 13:18:54" 起始時(shí)間點(diǎn)
--stop-datetime="2013-11-29 13:21:53" 結(jié)束時(shí)間點(diǎn)
2.3 undo log (回滾日志)
innodb存儲引擎對undo的管理采用段的方式。rollback segment稱為回滾段,每個(gè)回滾段中有1024個(gè)undo log segment。
undo log和redo log記錄物理日志不一樣,它是邏輯日志??梢哉J(rèn)為當(dāng)delete一條記錄時(shí),undo log中會記錄一條對應(yīng)的insert記錄,反之亦然,當(dāng)update一條記錄時(shí),它記錄一條對應(yīng)相反的update記錄。記錄事務(wù)中數(shù)據(jù)版本的反向變化。
當(dāng)執(zhí)行rollback時(shí),就可以從undo log中的邏輯記錄讀取到相應(yīng)的內(nèi)容并進(jìn)行回滾。有時(shí)候應(yīng)用到行版本控制的時(shí)候,也是通過undo log來實(shí)現(xiàn)的:當(dāng)讀取的某一行被其他事務(wù)鎖定時(shí),它可以從undo log中分析出該行記錄以前的數(shù)據(jù)是什么,從而提供該行版本信息,讓用戶實(shí)現(xiàn)非鎖定一致性讀取。
如果開啟了 innodb_file_per_table ,將放在每個(gè)表的.ibd文件中。
通過undo log記錄delete和update操作的結(jié)果發(fā)現(xiàn):(insert操作無需分析,就是插入行而已)
delete操作實(shí)際上不會直接刪除,而是將delete對象打上delete flag,標(biāo)記為刪除,最終的刪除操作是purge線程完成的。
update分為兩種情況:update的列是否是主鍵列。
如果不是主鍵列,在undo log中直接反向記錄是如何update的。即update是直接進(jìn)行的。如果是主鍵列,update分兩部執(zhí)行:先刪除該行,再插入一行目標(biāo)行。存儲位置
默認(rèn)情況下,undo 文件是保存在共享表空間的,也即 ibdatafile 文件中,當(dāng)數(shù)據(jù)庫中發(fā)生一些大的事務(wù)性操作的時(shí)候,要生成大量的 undo log 信息,這些信息全部保存在共享表空間中,因此共享表空間可能會變得很大,默認(rèn)情況下,也就是 undo log 使用共享表空間的時(shí)候,被“撐大”的共享表空間是不會、也不能自動(dòng)收縮的。因此,MySQL5.7 之后的“獨(dú)立 undo 表空間”的配置就顯得很有必要了。
2.4 思考
1 redo log 和binlog聯(lián)系?
通過事務(wù)id關(guān)聯(lián),崩潰恢復(fù)時(shí),接受“redolog prepare 并且binlog完整” 的情況
2 mysql 如何恢復(fù)數(shù)據(jù),比如某天下午兩點(diǎn)發(fā)現(xiàn)中午十二點(diǎn)有一次誤刪表,需要找回?cái)?shù)據(jù)?
(1)找到最近的一次全量備份,從這個(gè)備份恢復(fù)到臨時(shí)庫;
(2)從備份的時(shí)間點(diǎn)開始,將備份的 binlog 依次取出來,重放到中午誤刪表之前的那個(gè)時(shí)刻。
(3)把數(shù)據(jù)從臨時(shí)庫取出來,按需恢復(fù)到線上
3 redo log buffer 和 buffer pool 關(guān)系?
(1)修改數(shù)據(jù),先將數(shù)據(jù)頁讀到buffer pool中,進(jìn)行修改。bufferpool中的page就已經(jīng)和磁盤中的不一樣了,我們稱bufferpool中的page為臟頁。
(2)臟頁存在,系統(tǒng)斷電,會不會丟失數(shù)據(jù)呢?不會,因?yàn)橛涗浟藃edo log日志。
(3)redo log buffer 主要記錄的是buffer pool 的頁,做了什么改動(dòng),所以記的內(nèi)容不一樣。
以上就是關(guān)于pos機(jī)交易日志已滿請先結(jié)算,mysql總結(jié)筆記的知識,后面我們會繼續(xù)為大家整理關(guān)于pos機(jī)交易日志已滿請先結(jié)算的知識,希望能夠幫助到大家!
