linux mysql提交_MySQL 事務提交過程

開發老大要求通過binlog查詢一條被修改的數據,數據被查出后問我,有沒有可能binlog中不會記錄,回答不會,因為數據被修改,若失敗直接回滾,不會在binlog中記錄,此刻一個朋友用了洪荒之力告訴我,失敗的話也會記錄,坐地無語,因為他sqlserver dba,用sqlserver的思維考慮MySQL,哈哈哈哈哈,用實驗讓他閉嘴!

簡單測試步驟如下:

root(yoon)> flush logs;

Query OK, 0 rows affected (0.01 sec)

root((none))> show binlog events in 'mysql-bin.000041';

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| Log_name? ? ? ? | Pos | Event_type? | Server_id | End_log_pos | Info? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| mysql-bin.000041 |? 4 | Format_desc |? ? 232242 |? ? ? ? 120 | Server ver: 5.6.26-log, Binlog ver: 4 |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

root(yoon)> begin;

Query OK, 0 rows affected (0.00 sec)

root(yoon)> update yoon set id=7 where id=1;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1? Changed: 1? Warnings: 0

在沒有commit情況下,二進制日志的位置偏移量未發生變化:

root(yoon)> show binlog events in 'mysql-bin.000041';

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| Log_name? ? ? ? | Pos | Event_type? | Server_id | End_log_pos | Info? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

| mysql-bin.000041 |? 4 | Format_desc |? ? 232242 |? ? ? ? 120 | Server ver: 5.6.26-log, Binlog ver: 4 |

+------------------+-----+-------------+-----------+-------------+---------------------------------------+

root(yoon)> commit;

Query OK, 0 rows affected (1.01 sec)

提交后再次查看日志偏移量,發生變化,并記錄在binlog中

root(yoon)> show binlog events in 'mysql-bin.000041';

+------------------+-----+-------------+-----------+-------------+---------------------------------------------+

| Log_name? ? ? ? | Pos | Event_type? | Server_id | End_log_pos | Info? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

+------------------+-----+-------------+-----------+-------------+---------------------------------------------+

| mysql-bin.000041 |? 4 | Format_desc |? ? 232242 |? ? ? ? 120 | Server ver: 5.6.16-log, Binlog ver: 4? ? ? |

| mysql-bin.000041 | 120 | Query? ? ? |? ? 232242 |? ? ? ? 199 | BEGIN? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| mysql-bin.000041 | 199 | Query? ? ? |? ? 232242 |? ? ? ? 304 | use `yoon`; update yoon set id=7 where id=1 |

| mysql-bin.000041 | 304 | Xid? ? ? ? |? ? 232242 |? ? ? ? 335 | COMMIT /* xid=18 */? ? ? ? ? ? ? ? ? ? ? ? |

+------------------+-----+-------------+-----------+-------------+---------------------------------------------+

MySQL事務提交過程

開啟binlog后事務提交流程會變成兩階段提交,這里的兩階段提交并不涉及分布式事務,當然mysql把它稱之為內部xa事務(Distributed Transactions),與之對應的還有一個外部xa事務。

這里所謂的兩階段提交分別是prepare階段和commit階段。

內部xa事務主要是mysql內部為了保證binlog與redo log之間數據的一致性而存在的,這也是由其架構決定的(binlog在mysql層,而redo log 在存儲引擎層);

外部xa事務則是指支持多實例分布式事務,這個才算是真正的分布式事務。

既然是xa事務,必然涉及到兩階段提交,對于內部xa而言,同樣存在著提交的兩個階段。

下文會結合源碼詳細解讀內部xa的兩階段提交過程,以及各種情況下,mysqld crash后,mysql如何恢復來保證事務的一致性。

數據庫版本:5.6.16

操作系統版本:CentOS 6.5

配置文件參數:

log-bin=/my/log/mysql-bin

binlog_format=ROW

set autocommit=0

innodb_support_xa=1

sync_binlog=1

innodb_flush_log_at_trx_commit=1

【innodb_flush_log_at_trx_commit=1,sync_binlog=1

不同的模式區別在于,寫文件調用write和落盤fsync調用的頻率不同,所導致的后果是mysqld 或 os crash后,不嚴格的設置可能會丟失事務的更新。

雙一模式是最嚴格的模式,這種設置情況下,單機在任何情況下不會丟失事務更新。】

測試條件:

set autocommit=0;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (

`id` int(20) NOT NULL,

`account` varchar(20) NOT NULL,

`name` varchar(20) NOT NULL,

PRIMARY KEY (`id`),

KEY `id` (`id`) USING BTREE,

KEY `name` (`name`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

測試語句:

insert into user values(1, 'sanzhang', '張三');

commit;

prepare階段:

1.設置undo state=TRX_UNDO_PREPARED; //trx_undo_set_state_at_prepare調用

2.刷事務更新產生的redo日志;【步驟1產生的redo日志也會刷入】

MYSQL_BIN_LOG::prepare

ha_prepare_low

{

engine:

binlog_prepare

innobase_xa_prepare

mysql:

trx_prepare_for_mysql

{

1.trx_undo_set_state_at_prepare? ? //設置undo段的標記為TRX_UNDO_PREPARED

2.設置事務狀態為TRX_STATE_PREPARED

3.trx_flush_log_if_needed? //將產生的redolog刷入磁盤

}

}

commit階段:

1.將事務產生的binlog寫入文件,刷入磁盤;

2.設置undo頁的狀態,置為TRX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE;? // trx_undo_set_state_at_finish調用

3.記錄事務對應的binlog偏移,寫入系統表空間; //trx_sys_update_mysql_binlog_offset調用

MYSQL_BIN_LOG::commit

ordered_commit

{

1.FLUSH_STAGE

flush_cache_to_file? //? 刷binlog

2.SYNC_STAGE

sync_binlog_file? ? //Call fsync() to sync the file to disk.

3.COMMIT_STAGE

ha_commit_low

{

binlog_commit

innobase_commit

trx_commit(trx)

{

trx_write_serialisation_history(trx, mtr);? //更新binlog位點,設置undo狀態

trx_commit_in_memory(trx, lsn); //釋放鎖資源,清理保存點列表,清理回滾段

}

}

}

在任何情況下(機器掉電)mysqld crash或者os crash,MySQL仍然能保證數據庫的一致性。數據的一致性是如何做到的哪?正是二階段提交。

我們結合幾種場景來分析下二階段提交是如何做到的:

1.prepare階段,redo log落盤前,mysqld crash

2.prepare階段,redo log落盤后,binlog落盤前,mysqld crash

3.commit階段,binlog落盤后,mysqld crash

對于第一種情況,由于redo沒有落盤,毫無疑問,事務的更新肯定沒有寫入磁盤,數據庫的一致性受影響;

對于第二種情況,這時候redo log寫入完成,但binlog還未寫入,事務處于TRX_STATE_PREPARED狀態,這是提交還是回滾呢?

對于第三種情況,此時,redo log和binlog都已經落盤,只是undo狀態沒有更新,雖然redo log和binlog已經一致了,事務是否應該提交?

我們結合mysqld異常重啟后的執行邏輯以及關鍵的源代碼。

對于第三種情況,我們可以搜集到未提交事務的binlog event,所以需要提交;

對于第二種情況,由于binlog未寫入,需要通過執行回滾操作來保證數據庫的一致性。

異常重啟后,如何判斷事務該提交還是回滾

1.讀binlog日志,獲取崩潰時沒有提交的event;? //info->commit_list中含有該元素

2.若存在,則對應的事務要提交;否則需要回滾。

判斷事務提交或回滾源碼如下:

1a4d5bd2677b9902098b357f39c96be2.png

上面討論了兩階段提交的基本流程,以及服務器異常crash后,mysql如何重啟恢復保證binlog和數據的一致性。

簡而言之,對于異常的xa事務,若binlog已落盤,則事務應該提交;binlog未落盤,則事務就應該回滾。

//異常重啟后,回滾流程

innobase_rollback_by_xid

rollback_by_xid

trx_rollback_resurrected

trx_rollback_active

row_undo

{ //從回滾頁獲取undo記錄 //分析undo記錄類型 if (insert)

row_undo_ins else row_undo_mod

}

//異常重啟后,提交流程

commit_by_xid

trx_commit_for_mysql

//寫binlog接口

handler.cc:binlog_log_row

sql/binlog.cc:commit

mysys/my_sync:my_sync

sql/binlog.cc:sync_binlog_file

handler/ha_innodb.cc:innobase_xa_prepare

binlog日志文件是為了解決MySQL主從復制功能而引入的���份新日志文件,它包含了引發數據變更的事件日志集合。

從庫請求主庫發送 binlog 并通過日志事件還原數據寫入從庫,所以從庫的數據來源為 binlog。

這樣 MySQL 主庫只需做到 binlog 與本地數據一致就可以保證主從庫數據一致(暫且忽略網絡傳輸引發的主從不一致)。

0b1331709591d260c1c78e86d0c51c18.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393488.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393488.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393488.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spray.json_如何使用Spray-json(Un)在Akka HTTP中封送JSON

spray.jsonby Miguel Lopez由Miguel Lopez 如何使用Spray-json(Un)在Akka HTTP中封送JSON (How to (Un)marshal JSON in Akka HTTP with spray-json) In the previous post, we added JSON support to our Akka HTTP API using circe.在上一篇文章中 ,我們使用circ…

React單元測試:Jest + Enzyme(二)

前言 在上一篇教程中,我們成功搭建了基于Jest和Enzyme的單元測試框架并成功地跑起來第一個單元測試,可以點擊這里回顧一下。今天,我們重點討論如何通過Jest來mock數據。 什么是Mock Mock的簡單翻譯就是模擬。既可以模擬數據,也可以…

input file 文件上傳,js控制上傳文件的大小和格式

文件上傳一般是用jquery的uploadify,比較好用。后面會出文章介紹uploadify這個插件。 但是,有時候為了偷懶,直接就用input 的file進行文件和圖片等的上傳,input file 可以控制上傳的格式,但是是html5,很多瀏…

leetcode面試題 17.08. 馬戲團人塔(二分法)

有個馬戲團正在設計疊羅漢的表演節目,一個人要站在另一人的肩膀上。出于實際和美觀的考慮,在上面的人要比下面的人矮一點且輕一點。已知馬戲團每個人的身高和體重,請編寫代碼計算疊羅漢最多能疊幾個人。 示例: 輸入:…

如何選擇適合自己的CMS建站系統

如今做網站已不像過去那樣必須找網站公司才能建,因為網上針對建站的各種CMS建站系統層出不窮。像PageAdmin、DEDECMS、帝國CMS、Discuz等,這些CMS系統各有各的特點和優勢,小熊優化的小編我從事網站制作和網站優化多年,和很多建站朋…

python dict hash算法_2020年3月26日python學習筆記——hash

什么是哈希?hash,一般翻譯做散列、雜湊,或音譯為哈希,是把任意長度的輸入(又叫做預映射pre-image)通過散列算法變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠…

數據處理不等式:Data Processing Inequality

我是在差分隱私下看到的,新解決方案的可用性肯定小于原有解決方案的可用性,也就是說信息的后續處理只會降低所擁有的信息量。 那么如果這么說的話為什么還要做特征工程呢,這是因為該不等式有一個巨大的前提就是數據處理方法無比的強大&#x…

aws架構_如何使用AWS構建可擴展架構

aws架構What I learned building the StateOfVeganism ?我學到的建立素食主義的方法是什么? By now, we all know that news and media shape our views on the topics we discuss. Of course, this is different from person to person. Some might be influence…

gulp 實現sass自動化 ,監聽同步

實現功能 監聽scss文件   sass自動化 準備條件 1 .安裝gulp npm init ---->一直enter,會在當前目錄下生成一個package.json文件,記錄安裝的依賴模塊 npm install gulp --save-dev 2 .安裝gulp-ruby-sass npm install gulp-ruby-sass 你還需要安裝ruby環境…

leetcode面試題 10.03. 搜索旋轉數組(二分法)

搜索旋轉數組。給定一個排序后的數組,包含n個整數,但這個數組已被旋轉過很多次了,次數不詳。請編寫代碼找出數組中的某個元素,假設數組元素原先是按升序排列的。若有多個相同元素,返回索引值最小的一個。 示例1: 輸入…

MSSQL → 02:數據庫結構

一、數據庫的組成 在SQL Server 2008中,用戶如何訪問及使用數據庫,就需要正確了解數據庫中所有對象及其設置。數據庫就像一個容器,它里面除了存放著數據的表之外,還有視圖、存儲過程、觸發器、約束等數據庫對象。數據庫管理的核心…

JAVA拳皇_拳皇(Java簡單的小程序)代碼實例|chu

剛開始學習Java,看完老九君的視頻根據他的內容敲的代碼,感覺還挺有成就感的,畢竟剛學習Java。package helloasd;import java.util.*; public class hellojava { public static void main(String[] args) { Scanner input new Scanner(System…

mySQL教程 第9章 觸發器

第9章 觸發器 入的新數據放到new表,刪除的數據放到old表。 準備本章學習環境 連接數據庫schoolDB,刪除表TStudent,TScore和Tsubject中的所有數據。 delete from TStudent; delete from TScore; delete from TSubject; 向學生表插入兩條記錄 i…

vue使用python_如何使用Python和Vue創建兩人游戲

vue使用pythonby Neo Ighodaro由新Ighodaro 如何使用Python和Vue創建兩人游戲 (How to create a two-player game with Python and Vue) In this tutorial, we will create a realtime tic-tac-toe game using Python and Pusher channels. Here’s a demo of how the game wi…

掩碼圖制作photoshop__新手用

1.首先你得有一張圖,比如這樣的: 2.用PS打開他 3.左邊工具欄里(快速選擇工具W),選想顯示的部分 4.ctrlc復制一下,新建一張黑底圖粘貼上去或者白底圖時選中顯示區即花瓣右鍵反向右鍵填充成黑色 5.菜單欄->…

leetcode287. 尋找重復數(二分法)

給定一個包含 n 1 個整數的數組 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重復的整數。假設只有一個重復的整數,找出這個重復的數。 示例 1: 輸入: [1,3,4,2,2] 輸出: 2 代碼 class Solution {…

os-enviroment

pip3 install PyUserInput ping 是不帶協議的轉載于:https://www.cnblogs.com/liuweimingcprogram/p/10957592.html

java 壓縮 亂碼_如何解決java壓縮文件亂碼問題

用java來打包文件生成壓縮文件,有兩個地方會出現亂碼:內容的中文亂碼問題:修改sun的源碼。使用開源的類庫org.apache.tools.zip.ZipOutputStream和org.apache.tools.zip.ZipEntry,這兩個類ant.jar中有,可以下載使用即可…

Unity3D手機斗地主游戲開發實戰(02)_叫地主功能實現

大體思路 前面我們實現了點擊開始游戲按鈕,系統依次給玩家發牌的邏輯和動畫,并展示當前的手牌。這期我們繼續實現接下來的功能--叫地主。 1.首先這兩天,學習了DOTween,這是一個強大的Unity動畫插件,大家可以參考&#…

TensorFlow 學習(十)—— 工具函數

1. 基本 tf.clip_by_value() 截斷,常和對數函數結合使用 # 計算交叉熵crose_ent -tf.reduce_mean(tf.log(y_*tf.clip_by_value(y, 1e-10, 1.))) a tf.reshape(tf.range(6, dtypetf.float32), [2, 3]) tf.clip_by_value(a, 2.5, 4.5) # 將值限定在 2.5 …