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