Mysql高手系列 - 第14篇:詳解事務


這是Mysql系列第14篇。

環境:mysql5.7.25,cmd命令中進行演示。

開發過程中,會經常用到數據庫事務,所以本章非常重要。

本篇內容

  1. 什么是事務,它有什么用?
  2. 事務的幾個特性
  3. 事務常見操作指令詳解
  4. 事務的隔離級別詳解
  5. 臟讀、不可重復讀、可重復讀、幻讀詳解
  6. 演示各種隔離級別產生的現象
  7. 關於隔離級別的選擇

什么是事務?

數據庫中的事務是指對數據庫執行一批操作,這些操作最終要么全部執行成功,要么全部失敗,不會存在部分成功的情況。

舉個例子

比如A用戶給B用戶轉賬100操作,過程如下:

1.從A賬戶扣100
2.給B賬戶加100

如果在事務的支持下,上面最終只有2種結果:

  1. 操作成功:A賬戶減少100;B賬戶增加100
  2. 操作失敗:A、B兩個賬戶都沒有發生變化

如果沒有事務的支持,可能出現錯:A賬戶減少了100,此時系統掛了,導致B賬戶沒有加上100,而A賬戶憑空少了100。

事務的幾個特性(ACID)

原子性(Atomicity)

事務的整個過程如原子操作一樣,最終要么全部成功,或者全部失敗,這個原子性是從最終結果來看的,從最終結果來看這個過程是不可分割的。

一致性(Consistency)

事務開始之前、執行中、執行完畢,這些時間點,多個人去觀察事務操作的數據的時候,看到的數據都是一致的,比如在事務操作過程中,A連接看到的是100,那么B此時也去看的時候也是100,不會說AB看到的數據不一樣,他們在某個時間點看到的數據是一致的。

隔離性(Isolation)

一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對並發的其他事務是隔離的,並發執行的各個事務之間不能互相干擾。

持久性(Durability)

一個事務一旦提交,他對數據庫中數據的改變就應該是永久性的。當事務提交之后,數據會持久化到硬盤,修改是永久性的。

Mysql中事務操作

mysql中事務默認是隱式事務,執行insert、update、delete操作的時候,數據庫自動開啟事務、提交或回滾事務。

是否開啟隱式事務是由變量autocommit控制的。

所以事務分為隱式事務顯式事務

隱式事務

事務自動開啟、提交或回滾,比如insert、update、delete語句,事務的開啟、提交或回滾由mysql內部自動控制的。

查看變量autocommit是否開啟了自動提交

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)

autocommit為ON表示開啟了自動提交。

顯式事務

事務需要手動開啟、提交或回滾,由開發者自己控制。

2種方式手動控制事務:

方式1:

語法:

//設置不自動提交事務
set autocommit=0;
//執行事務操作
commit|rollback;

示例1:提交事務操作,如下:

mysql> create table test1 (a int);
Query OK, 0 rows affected (0.01 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

示例2:回滾事務操作,如下:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values(2);
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

可以看到上面數據回滾了。

我們把autocommit還原回去:

mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)

方式2:

語法:

start transaction;//開啟事務
//執行事務操作
commit|rollback;

示例1:提交事務操作,如下:

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test1 values (3);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

上面成功插入了2條數據。

示例2:回滾事務操作,如下:

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from test1;
Query OK, 3 rows affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

上面事務中我們刪除了test1的數據,顯示刪除了3行,最后回滾了事務。

savepoint關鍵字

在事務中我們執行了一大批操作,可能我們只想回滾部分數據,怎么做呢?

我們可以將一大批操作分為幾個部分,然后指定回滾某個部分。可以使用savepoin來實現,效果如下:

先清除test1表數據:

mysql> delete from test1;
Query OK, 3 rows affected (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

演示savepoint效果,認真看:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (1);
Query OK, 1 row affected (0.00 sec)

mysql> savepoint part1;//設置一個保存點
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (2);
Query OK, 1 row affected (0.00 sec)

mysql> rollback to part1;//將savepint = part1的語句到當前語句之間所有的操作回滾
Query OK, 0 rows affected (0.00 sec)

mysql> commit;//提交事務
Query OK, 0 rows affected (0.00 sec)
    
mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

從上面可以看出,執行了2次插入操作,最后只插入了1條數據。

savepoint需要結合rollback to sp1一起使用,可以將保存點sp1rollback to之間的操作回滾掉。

只讀事務

表示在事務中執行的是一些只讀操作,如查詢,但是不會做insert、update、delete操作,數據庫內部對只讀事務可能會有一些性能上的優化。

用法如下:

start transaction read only;

示例:

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction read only;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    1 |
+------+
2 rows in set (0.00 sec)

mysql> delete from test1;
ERROR 1792 (25006): Cannot execute statement in a READ ONLY transaction.
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    1 |
+------+
2 rows in set (0.00 sec)

只讀事務中執行delete會報錯。

事務中的一些問題

這些問題主要是基於數據在多個事務中的可見性來說的。

臟讀

一個事務在執行的過程中讀取到了其他事務還沒有提交的數據。
這個還是比較好理解的。

讀已提交

從字面上我們就可以理解,即一個事務操作過程中可以讀取到其他事務已經提交的數據。

事務中的每次讀取操作,讀取到的都是數據庫中其他事務已提交的最新的數據(相當於當前讀)

可重復讀

一個事務操作中對於一個讀取操作不管多少次,讀取到的結果都是一樣的。

幻讀

臟讀、不可重復讀、可重復讀、幻讀,其中最難理解的是幻讀

以mysql為例:

幻讀在可重復讀的模式下才會出現,其他隔離級別中不會出現

幻讀現象例子:

可重復讀模式下,比如有個用戶表,手機號碼為主鍵,有兩個事物進行如下操作

事務A操作如下:
1、打開事務
2、查詢號碼為X的記錄,不存在
3、插入號碼為X的數據,插入報錯(為什么會報錯,先向下看)
4、查詢號碼為X的記錄,發現還是不存在(由於是可重復讀,所以讀取記錄X還是不存在的)

事物B操作:在事務A第2步操作時插入了一條X的記錄,所以會導致A中第3步插入報錯(違反了唯一約束)

上面操作對A來說就像發生了幻覺一樣,明明查詢X(A中第二步、第四步)不存在,但卻無法插入成功

幻讀可以這么理解:事務中后面的操作(插入號碼X)需要上面的讀取操作(查詢號碼X的記錄)提供支持,但讀取操作卻不能支持下面的操作時產生的錯誤,就像發生了幻覺一樣。

如果還是理解不了的,繼續向下看,后面后詳細的演示。

事務的隔離級別

當多個事務同時進行的時候,如何確保當前事務中數據的正確性,比如A、B兩個事物同時進行的時候,A是否可以看到B已提交的數據或者B未提交的數據,這個需要依靠事務的隔離級別來保證,不同的隔離級別中所產生的效果是不一樣的。

事務隔離級別主要是解決了上面多個事務之間數據可見性及數據正確性的問題。

隔離級別分為4種:

  1. 讀未提交:READ-UNCOMMITTED
  2. 讀已提交:READ-COMMITTED
  3. 可重復讀:REPEATABLE-READ
  4. 串行:SERIALIZABLE

上面4中隔離級別越來越強,會導致數據庫的並發性也越來越低。

查看隔離級別

mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)

隔離級別的設置

分2步驟,修改文件、重啟mysql,如下:

修改mysql中的my.init文件,我們將隔離級別設置為:READ-UNCOMMITTED,如下:

# 隔離級別設置,READ-UNCOMMITTED讀未提交,READ-COMMITTED讀已提交,REPEATABLE-READ可重復讀,SERIALIZABLE串行
transaction-isolation=READ-UNCOMMITTED

以管理員身份打開cmd窗口,重啟mysql,如下:

C:\Windows\system32>net stop mysql
mysql 服務正在停止..
mysql 服務已成功停止。

C:\Windows\system32>net start mysql
mysql 服務正在啟動 .
mysql 服務已經啟動成功。

各種隔離級別中會出現的問題

隔離級別 臟讀 不可重復讀 幻讀
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE

表格中和網上有些不一樣,主要是幻讀這塊,幻讀只會在可重復讀級別中才會出現,其他級別下不存在。

下面我們來演示一下,各種隔離級別中可見性的問題,開啟兩個窗口,叫做A、B窗口,兩個窗口中登錄mysql。

READ-UNCOMMITTED:讀未提交

將隔離級別置為READ-UNCOMMITTED

# 隔離級別設置,READ-UNCOMMITTED讀未提交,READ-COMMITTED讀已提交,REPEATABLE-READ可重復讀,SERIALIZABLE串行
transaction-isolation=READ-UNCOMMITTED

重啟mysql:

C:\Windows\system32>net stop mysql
mysql 服務正在停止..
mysql 服務已成功停止。

C:\Windows\system32>net start mysql
mysql 服務正在啟動 .
mysql 服務已經啟動成功。

查看隔離級別:

mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | READ-UNCOMMITTED |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)

先清空test1表數據:

delete from test1;
select * from test1;

按時間順序在2個窗口中執行下面操作:

時間 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3 start transaction;
T4 insert into test1 values (1);
T5 select * from test1;
T6 select * from test1;
T7 commit;
T8 commit;

A窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

B窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

看一下:

T2-A:無數據,T6-A:有數據,T6時刻B還未提交,此時A已經看到了B插入的數據,說明出現了臟讀

T2-A:無數據,T6-A:有數據,查詢到的結果不一樣,說明不可重復讀

結論:讀未提交情況下,可以讀取到其他事務還未提交的數據,多次讀取結果不一樣,出現了臟讀、不可重復讀

READ-COMMITTED:讀已提交

將隔離級別置為READ-COMMITTED

# 隔離級別設置,READ-UNCOMMITTED讀未提交,READ-COMMITTED讀已提交,REPEATABLE-READ可重復讀,SERIALIZABLE串行
transaction-isolation=READ-COMMITTED

重啟mysql:

C:\Windows\system32>net stop mysql
mysql 服務正在停止..
mysql 服務已成功停止。

C:\Windows\system32>net start mysql
mysql 服務正在啟動 .
mysql 服務已經啟動成功。

查看隔離級別:

mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)

先清空test1表數據:

delete from test1;
select * from test1;

按時間順序在2個窗口中執行下面操作:

時間 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3 start transaction;
T4 insert into test1 values (1);
T5 select * from test1;
T6 select * from test1;
T7 commit;
T8 select * from test1;
T9 commit;

A窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

B窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

看一下:

T5-B:有數據,T6-A窗口:無數據,A看不到B的數據,說明沒有臟讀

T6-A窗口:無數據,T8-A:看到了B插入的數據,此時B已經提交了,A看到了B已提交的數據,說明可以讀取到已提交的數據

T2-A、T6-A:無數據,T8-A:有數據,多次讀取結果不一樣,說明不可重復讀

結論:讀已提交情況下,無法讀取到其他事務還未提交的數據,可以讀取到其他事務已經提交的數據,多次讀取結果不一樣,未出現臟讀,出現了讀已提交、不可重復讀。

REPEATABLE-READ:可重復讀

將隔離級別置為REPEATABLE-READ

# 隔離級別設置,READ-UNCOMMITTED讀未提交,READ-COMMITTED讀已提交,REPEATABLE-READ可重復讀,SERIALIZABLE串行
transaction-isolation=REPEATABLE-READ

重啟mysql:

C:\Windows\system32>net stop mysql
mysql 服務正在停止..
mysql 服務已成功停止。

C:\Windows\system32>net start mysql
mysql 服務正在啟動 .
mysql 服務已經啟動成功。

查看隔離級別:

mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)

先清空test1表數據:

delete from test1;
select * from test1;

按時間順序在2個窗口中執行下面操作:

時間 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3 start transaction;
T4 insert into test1 values (1);
T5 select * from test1;
T6 select * from test1;
T7 commit;
T8 select * from test1;
T9 commit;
T10 select * from test1;

A窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    1 |
+------+
2 rows in set (0.00 sec)

B窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test1 values (1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test1;
+------+
| a    |
+------+
|    1 |
|    1 |
+------+
2 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

看一下:

T2-A、T6-A窗口:無數據,T5-B:有數據,A看不到B的數據,說明沒有臟讀

T8-A:無數據,此時B已經提交了,A看不到B已提交的數據,A中3次讀的結果一樣都是沒有數據的,說明可重復讀

結論:可重復讀情況下,未出現臟讀,未讀取到其他事務已提交的數據,多次讀取結果一致,即可重復讀。

幻讀演示

幻讀只會在REPEATABLE-READ(可重復讀)級別下出現,需要先把隔離級別改為可重復讀。

將隔離級別置為REPEATABLE-READ

# 隔離級別設置,READ-UNCOMMITTED讀未提交,READ-COMMITTED讀已提交,REPEATABLE-READ可重復讀,SERIALIZABLE串行
transaction-isolation=REPEATABLE-READ

重啟mysql:

C:\Windows\system32>net stop mysql
mysql 服務正在停止..
mysql 服務已成功停止。

C:\Windows\system32>net start mysql
mysql 服務正在啟動 .
mysql 服務已經啟動成功。

查看隔離級別:

mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)

准備數據:

mysql> create table t_user(id int primary key,name varchar(16) unique key);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t_user values (1,'路人甲Java'),(2,'路人甲Java');
ERROR 1062 (23000): Duplicate entry '路人甲Java' for key 'name'

mysql> select * from t_user;
Empty set (0.00 sec)

上面我們創建t_user表,name添加了唯一約束,表示name不能重復,否則報錯。

按時間順序在2個窗口中執行下面操作:

時間 窗口A 窗口B
T1 start transaction;
T2 start transaction;
T3 -- 插入路人甲Java
insert into t_user values (1,'路人甲Java');
T4 select * from t_user;
T5 -- 查看路人甲Java是否存在
select * from t_user where name='路人甲Java';
T6 commit;
T7 -- 插入路人甲Java
insert into t_user values (2,'路人甲Java');
T8 -- 查看路人甲Java是否存在
select * from t_user where name='路人甲Java';
T9 commit;

A窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user where name='路人甲Java';
Empty set (0.00 sec)

mysql> insert into t_user values (2,'路人甲Java');
ERROR 1062 (23000): Duplicate entry '路人甲Java' for key 'name'
mysql> select * from t_user where name='路人甲Java';
Empty set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

B窗口如下:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_user values (1,'路人甲Java');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_user;
+----+---------------+
| id | name          |
+----+---------------+
|  1 | 路人甲Java    |
+----+---------------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

看一下:

A想插入數據路人甲Java,插入之前先查詢了一下(T5時刻)該用戶是否存在,發現不存在,然后在T7時刻執行插入,報錯了,報數據已經存在了,因為T6時刻B已經插入了路人甲Java

然后A有點郁悶,剛才查的時候不存在的,然后A不相信自己的眼睛,又去查一次(T8時刻),發現路人甲Java還是不存在的。

此時A心里想:數據明明不存在啊,為什么無法插入呢?這不是懵逼了么,A覺得如同發生了幻覺一樣。

SERIALIZABLE:串行

SERIALIZABLE會讓並發的事務串行執行(多個事務之間讀寫、寫讀、寫寫會產生互斥,效果就是串行執行,多個事務之間的讀讀不會產生互斥)。

讀寫互斥:事務A中先讀取操作,事務B發起寫入操作,事務A中的讀取會導致事務B中的寫入處於等待狀態,直到A事務完成為止。

表示我開啟一個事務,為了保證事務中不會出現上面說的問題(臟讀、不可重復讀、讀已提交、幻讀),那么我讀取的時候,其他事務有修改數據的操作需要排隊等待,等待我讀取完成之后,他們才可以繼續。

寫讀、寫寫也是互斥的,讀寫互斥類似。

這個類似於java中的java.util.concurrent.lock.ReentrantReadWriteLock類產生的效果。

下面演示讀寫互斥的效果。

將隔離級別置為SERIALIZABLE

# 隔離級別設置,READ-UNCOMMITTED讀未提交,READ-COMMITTED讀已提交,REPEATABLE-READ可重復讀,SERIALIZABLE串行
transaction-isolation=SERIALIZABLE

重啟mysql:

C:\Windows\system32>net stop mysql
mysql 服務正在停止..
mysql 服務已成功停止。

C:\Windows\system32>net start mysql
mysql 服務正在啟動 .
mysql 服務已經啟動成功。

查看隔離級別:

mysql> show variables like 'transaction_isolation';
+-----------------------+--------------+
| Variable_name         | Value        |
+-----------------------+--------------+
| transaction_isolation | SERIALIZABLE |
+-----------------------+--------------+
1 row in set, 1 warning (0.00 sec)

先清空test1表數據:

delete from test1;
select * from test1;

按時間順序在2個窗口中執行下面操作:

時間 窗口A 窗口B
T1 start transaction;
T2 select * from test1;
T3 start transaction;
T4 insert into test1 values (1);
T5 commit;
T6 commit;

按時間順序運行上面的命令,會發現T4-B這樣會被阻塞,直到T5-A執行完畢。

上面這個演示的是讀寫互斥產生的效果,大家可以自己去寫一下寫讀、寫寫互斥的效果。

可以看出來,事務只能串行執行了。串行情況下不存在臟讀、不可重復讀、幻讀的問題了。

關於隔離級別的選擇

  1. 需要對各種隔離級別產生的現象非常了解,然后選擇的時候才能游刃有余
  2. 隔離級別越高,並發性也低,比如最高級別SERIALIZABLE會讓事物串行執行,並發操作變成串行了,會導致系統性能直接降低。
  3. 具體選擇哪種需要結合具體的業務來選擇。
  4. 讀已提交(READ-COMMITTED)通常用的比較多。

總結

  1. 理解事務的4個特性:原子性、一致性、隔離性、持久性
  2. 掌握事務操作常見命令的介紹
  3. set autocommit可以設置是否開啟自動提交事務
  4. start transaction:開啟事務
  5. start transaction read only:開啟只讀事物
  6. commit:提交事務
  7. rollback:回滾事務
  8. savepoint:設置保存點
  9. rollback to 保存點:可以回滾到某個保存點
  10. 掌握4種隔離級別及了解其特點
  11. 了解臟讀、不可重復讀、幻讀

Mysql系列目錄

  1. 第1篇:mysql基礎知識
  2. 第2篇:詳解mysql數據類型(重點)
  3. 第3篇:管理員必備技能(必須掌握)
  4. 第4篇:DDL常見操作
  5. 第5篇:DML操作匯總(insert,update,delete)
  6. 第6篇:select查詢基礎篇
  7. 第7篇:玩轉select條件查詢,避免采坑
  8. 第8篇:詳解排序和分頁(order by & limit)
  9. 第9篇:分組查詢詳解(group by & having)
  10. 第10篇:常用的幾十個函數詳解
  11. 第11篇:深入了解連接查詢及原理
  12. 第12篇:子查詢
  13. 第13篇:細說NULL導致的神坑,讓人防不勝防

mysql系列大概有20多篇,喜歡的請關注一下,歡迎大家加我微信itsoku或者留言交流mysql相關技術!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM