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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

《MySQL——事务》

發布時間:2023/12/1 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《MySQL——事务》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 事務的必要性
  • MySQL中如何控制事務
  • 手動開啟事務
  • 事務的四大特征
    • 事務的四大特征
    • 事務開啟方式
    • 事務手動提交與手動回滾
  • 事務的隔離性
    • 臟讀現象
    • 不可重復讀現象
    • 幻讀現象
    • 串行化
  • 一些補充
    • 使用長事務的弊病
    • `commit work and chain`的語法是做什么用的?
    • 怎么查詢各個表中的長事務?
    • 如何避免長事務的出現?
    • 事務隔離是怎么通過read-view(讀視圖)實現的?
  • 參考

事務的必要性

mysql中,事務是一個最小的不可分割的工作單元。事務能夠保證一個業務的完整性。
比如我們的銀行轉賬:

-- a -> -100 UPDATE user set money = money - 100 WHERE name = 'a';-- b -> +100 UPDATE user set money = money + 100 WHERE name = 'b';

如果程序中,只有一條語句執行成功了,而另外一條沒有執行成功,就會出現前后不一致。就會有人白嫖。
因此,在執行多條有關聯 SQL 語句時,事務可能會要求這些 SQL 語句要么同時執行成功,要么就都執行失敗。
也就是說事務具有原子性。

MySQL中如何控制事務

1、mysql是默認開啟事務的(自動提交)
默認事務開啟的作用:

-- 查詢事務的自動提交狀態 SELECT @@AUTOCOMMIT; +--------------+ | @@AUTOCOMMIT | +--------------+ | 1 | +--------------+

當我們執行一個sql語句時候,效果會立即體現出來,且不能回滾。
回滾舉例

CREATE DATABASE bank;USE bank;CREATE TABLE user (id INT PRIMARY KEY,name VARCHAR(20),money INT );INSERT INTO user VALUES (1, 'a', 1000);SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+

執行插入語句后數據立刻生效,原因是 MySQL 中的事務自動將它提交到了數據庫中。那么所謂回滾的意思就是,撤銷執行過的所有 SQL 語句,使其回滾到最后一次提交數據時的狀態。

在 MySQL 中使用 ROLLBACK 執行回滾:
由于所有執行過的 SQL 語句都已經被提交過了,所以數據并沒有發生回滾。

-- 回滾到最后一次提交 ROLLBACK;SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+

將自動提交關閉后,可以數據回滾:

-- 關閉自動提交 SET AUTOCOMMIT = 0;-- 查詢自動提交狀態 SELECT @@AUTOCOMMIT; +--------------+ | @@AUTOCOMMIT | +--------------+ | 0 | +--------------+

現在我們測試一下:

INSERT INTO user VALUES (2, 'b', 1000);-- 關閉 AUTOCOMMIT 后,數據的變化是在一張虛擬的臨時數據表中展示, -- 發生變化的數據并沒有真正插入到數據表中。 SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | | 2 | b | 1000 | +----+------+-------+-- 數據表中的真實數據其實還是: +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+-- 由于數據還沒有真正提交,可以使用回滾 ROLLBACK;-- 再次查詢 SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+

可以使用COMMIT將虛擬的數據真正提交到數據庫中:

INSERT INTO user VALUES (2, 'b', 1000); -- 手動提交數據(持久性), -- 將數據真正提交到數據庫中,執行后不能再回滾提交過的數據。 COMMIT;-- 提交后測試回滾 ROLLBACK;-- 再次查詢(回滾無效了) SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | | 2 | b | 1000 | +----+------+-------+

總結

1、查看自動提交狀態: select @@AUTOCOMMIT;
2、設置自動提交狀態: set AUTOCOMMIT = 0;
3、手動提交: 在 @@AUTOCOMMIT = 0 時,可以使用commit 命令提交事務
4、事務回滾: 在 @@AUTOCOMMIT = 0 時,可以使用rollback 命令回滾事務

事務給我們提供了一個可以反悔的機會,假設在轉賬時發生了意外,就可以使用 ROLLBACK 回滾到最后一次提交的狀態。假設數據沒有發生意外,這時可以手動將數據COMMIT 到數據表中。

手動開啟事務

可以使用BEGIN 或者 START TRANSACTION 手動開啟一個事務。

-- 使用 BEGIN 或者 START TRANSACTION 手動開啟一個事務 -- START TRANSACTION; BEGIN; UPDATE user set money = money - 100 WHERE name = 'a'; UPDATE user set money = money + 100 WHERE name = 'b';-- 由于手動開啟的事務沒有開啟自動提交, -- 此時發生變化的數據仍然是被保存在一張臨時表中。 SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 900 | | 2 | b | 1100 | +----+------+-------+-- 測試回滾 ROLLBACK;SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | | 2 | b | 1000 | +----+------+-------+

當然事務開啟之后,使用commit提交后就不能回滾了。

事務的四大特征

事務的四大特征

A 原子性:事務是最小的單位,不可以分割
C 一致性:事務要求同一事務中的sql語句,必須要保證同時成功或者同時失敗
I 隔離性:事務1 和事務2 之間是具有隔離性的
D 持久性:事務一旦結束(commit or rollback),就不可以返回

事務開啟方式

1、修改默認提交 set autocommit = 0;
2、begin
3、start transaction

事務手動提交與手動回滾

手動提交:commit
手動回滾:rollback

事務的隔離性

事務的隔離性:

1、read uncommitted; 讀未提交的
2、read committed; 讀已經提交的
3、repeatable read; 可以重復讀
4、serializable; 串行化

臟讀現象

在read uncommitted的隔離級別下:
臟讀:一個事務讀到了另外有一個事務沒有提交的數據
實際開發不允許臟讀出現。
如果有兩個事務 a、b
a事務對數據進行操作,在操作的過程中,事務并沒有被提交,但是b可以看見a操作的結果。b看到轉賬到了,然后就不管了。后面a進行rollback操作,錢又回去了,完成白嫖。

不可重復讀現象

在read committed的隔離級別下:
小王一開始開啟了一個事務,然后提交了幾個數據,然后出去抽煙。
在他抽煙的時候,小明在其他電腦上開啟了一個事務,然后對那個表提交了一個數據。
小王煙抽完了,然后統計表中數據,發現不對勁。前后不一致了。

幻讀現象

在repeatable read;的隔離級別下:
事務a和事務b同時操作一張表,事務a提交的數據也不能被事務b讀到,就可以造成幻讀。
可以觀察如下步驟:
小明 在杭州 開啟一個事務;
小王 在北京 開啟一個事務;
小明 對table進行插入數據操作,然后commit;然后查看表,發現操作成功
小王在對table進行插入之前也查看表,然而并沒有小明插入的數據,于是乎他插入了同樣的一條數據,數據庫報錯。
小王很是疑惑,這就是幻讀現象。

串行化

在serializable的隔離級別下:
當user表被事務a操作的時候,事務b里面的寫操作是不可以進行的,會進入排隊狀態(串行化)。
“讀-讀”在串行化隔離級別允許并發。
直到事務a結束之后,事務b的寫入操作才會執行。
串行化的問題是性能特差。
一般來說,隔離級別越高,性能越差。
MySQL默認隔離級別是:repeatable read;

一些補充

使用長事務的弊病

存儲空間上來說:
長事務意味著系統里面會存在很老的事務視圖。由于這些事務隨時可能訪問數據庫里面的任何數據,所以這個事務提交之前,數據庫里面它可能用到的回滾記錄都必須保留,這就會導致大量占用存儲空間。
長事務還占用鎖資源,也可能拖垮整個庫。

commit work and chain的語法是做什么用的?

提交上一個事務,并且再開啟一個新的事務。它的功能等效于:commit + begin。

怎么查詢各個表中的長事務?

這個表中記錄了所有正在運行的事務信息,里面有事務的開始時間??梢詮倪@里看出哪些事務運行的時間比較長。

select * from information_schema.innodb_trx;

如何避免長事務的出現?

數據庫方面:

a.設置autocommit=1,不要設置為0。 b.寫腳本監控information_schemal.innodb_trx表中數據內容,發現長事務,kill掉它。 c.配置SQL語句所能執行的最大運行時間,如果查過最大運行時間后,中斷這個事務

SQL語句方面:

設置回滾表空單獨存放,便于回收表空間

業務代碼方面:

1、檢查業務邏輯代碼,能拆分為小事務的不要用大事務。
2、檢查代碼,把沒有必要的select語句被事務包裹的情況去掉

事務隔離是怎么通過read-view(讀視圖)實現的?

每一行數有多個版本,當我們要去讀取數據的時候,要判斷這個數據的版本號,對當前事務而言,是否可見,如果不可見,則要根據回滾日志計算得到上一個版本。如果上一個版本也不符合要求,則要找到再上一個版本,
直到找到對應正確的數據版本。

參考

一天學會MySQL
https://time.geekbang.org/column/article/68963

總結

以上是生活随笔為你收集整理的《MySQL——事务》的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。