1. 程式人生 > 其它 >crontab定時備份docker部署的gitea上傳到華為OBS

crontab定時備份docker部署的gitea上傳到華為OBS

Mysql-事務

本質是一組不可分割SQL語句,所以事務不可以巢狀

1. 概念

●事務是一種機制、一個操作序列,包含了一組資料庫操作命令,並且把所有的命令作為--個整體一起向系統提交或撤銷操作請求,即這組資料庫命令要麼都執行,要麼都不執行。

●事務是-一個不可分割的工作邏輯單元,在資料庫系統上執行併發操作時,事務是最小的控制單元。

●事務適用於多使用者同時操作的資料庫系統的場景,如銀行、保險公司及證券交易系統等等。

●事務通過事務的整體性以保證資料的一致性。

●事務能夠提高在向表中更新和插入資訊期間的可靠性。

2. ACID

  • 原子性Atomicity

    一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。

  • 一致性Consistency

    在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續資料庫可以自發性地完成預定的工作。

    一致性問題

    • 髒讀

      當一個事務正在訪問資料,並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外a個事務也訪問這個資料,然後使用了這個資料。

    • 不可重複讀

      指在一個事務內,多次讀同一資料。在這個事務還沒有結束時,另外一個事務也訪問該同一資料。那麼,在第一個事務中的兩次讀資料之間,由於第二個事務的修改,那麼第一個事務兩次讀到的的資料可能是不一樣的。這樣就發生了在一個事務內兩次讀到的資料是不一樣的,因此稱為是不可重複讀。( 即不能讀到相同的資料內容)

    • 幻讀

      一個事務對一個表中的資料進行了修改,這種修改涉及到表中的全部資料行。同時,另一個事務也修改這個表中的資料,這種修改是向表中插入一 行新資料。那麼,操作前一個事務的使用者會發現表中還有沒有修改的資料行,就好象發生了幻覺一 樣。

    • 丟失更新

      兩個事務同時讀取同一條記錄,A先修改記錄,B也修改記錄( B不知道A修改過),B提交資料後B的修改結果覆蓋了A的修改結果。

  • 隔離性Isolation

    資料庫允許多個併發事務同時對其資料進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時由於交叉執行而導致資料的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和序列化(Serializable)。

    • 隔離級別

      • Read Uncommitted(讀取未提交內容)RU

        允許髒讀,即允許一個事務可以看到其他事務未提交的修改。

      • Read Committed(讀取提交內容)其他sql資料庫的預設級別RC

        允許一個事務只能看到其他事務已經提交的修改,未提交的修改是不可見的。防止髒讀。

      • Repeatable Read(可重複讀)mysql預設級別RR

        確保如果在一個事務中執行兩次相同的SELECT語句,都能得到相同的結果,不管其他事務是否提交這些修改。可以防止髒讀和不可重複讀

      • Serializable(可序列化)

        完全序列化的讀,將一個事務與其他事務完全地隔離。每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞。可以防止髒讀,不可重複讀取和幻讀,(事務序列化)會降低資料庫的效率。

  • 永續性Durability

    事務處理結束後,對資料的修改就是永久的,即便系統故障也不會丟失。

3. 事務的查詢與設定

  • 查詢全域性事務隔離級別:global

    show global variables like '%isolation%';
    SELECT @@global.tx_isolation;
    
  • 查詢會話事務隔離級別:session

    show session variables like '%isolation%';
    SELECT @@session.tx_isolation;
    SELECT @@tx_isolation;
    
  • 設定全域性事務隔離級別

    set global transaction isolation level <隔離級別>;
    
    • 對所有會話生效
  • 設定會話事務隔離級別

    set session transaction isolation level read committed;
    
    • 對當前會話生效,有會話事務隔離優先適用
  • 事務控制語句

    • BEGIN 或 START TRANSACTION:開始一個事務

    • COMMIT 也可以使用 COMMIT WORK 事務確認

    • ROLLBACK 也可以使用 ROLLBACK WORK 事務回滾

      回滾會結束使用者的事務,並撤銷正在進行的所有未提交的修改。

    • SAVEPOINT identifier:建立回滾點 (identifier是回滾點名稱,自定義)

    • RELEASE SAVEPOINT identifier 刪除一個事務的儲存點,當沒有指定的儲存點時,執行該語句會丟擲一個異常;

    • ROLLBACK TO identifier :把事務回滾到標記點;

  • 事務的自動提交功能

    直接用 SET 來改變 MySQL 的自動提交模式:

    SET AUTOCOMMIT=0 禁止自動提交
    SET AUTOCOMMIT=1 開啟自動提交
    

    mysql自動開啟自動提交

    即每一條sql語句都可以視為一個事務,當關閉自動提交後,必須通過commit才能完成一次資料提交

    • 關閉了自動提交後,開啟一個事務不再以begin開始。

4.事務隔離級別測試。

4.1 mysql預設隔離級別RR

4.1.1 當無主鍵的時候

現有一張資料表test_tb1。

mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
+------+--------+-------+
2 rows in set (0.00 sec)

現在使用兩個終端連線資料庫。

使用終端1檢視全域性會話事務隔離級別,為RR。(可重複讀,即在開啟一個事務後,使用select語句檢視的效果一致,無論是否有其他事務提交)

##Centos7-1:1
mysql> show global variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

在終端1開啟一個事務。

##Centos7-1:1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
+------+--------+-------+
2 rows in set (0.00 sec)

在終端2提交一個修改。

##Centos7-1:2
mysql> insert into test_tb1 values (3,'david',1500);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
|    3 | david  |  1500 |
+------+--------+-------+
3 rows in set (0.00 sec)

在終端1使用select語句再次檢視,select語句與原結果一致(事務尚未提交)

##Centos7-1:1
mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
+------+--------+-------+
2 rows in set (0.00 sec)

在終端1再次插入id為3的記錄。

##Centos7-1:1
mysql> insert into test_tb1 values(3,'nike',1250);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
|    3 | nike   |  1250 |
+------+--------+-------+
3 rows in set (0.00 sec)

終端2再次select檢視效果,記錄3依舊為david。

##Centos7-1:2
mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
|    3 | david  |  1500 |
+------+--------+-------+
3 rows in set (0.00 sec)

終端1提交事務

##Centos7-1:1
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

終端2再次使用select檢視修改效果,出現兩個id為3的記錄。

mysql> select * from test_tb1;
+------+--------+-------+
| id   | name   | money |
+------+--------+-------+
|    1 | nancy  |   500 |
|    2 | jackie |  1000 |
|    3 | david  |  1500 |
|    3 | nike   |  1250 |
+------+--------+-------+
4 rows in set (0.00 sec)

4.1.2 當id為主鍵的時候。

首先刪除nike記錄。並將id列設定為主鍵。

mysql> delete from test_tb1 where name='nike';
Query OK, 1 row affected (0.00 sec)

mysql> alter table test_tb1 add primary key(id);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

在終端1開啟一個事務,並插入一個id為4的記錄。

##Centos7-1:1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test_tb1 values (4,'xiaoming',2000);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test_tb1;
+----+----------+-------+
| id | name     | money |
+----+----------+-------+
|  1 | nancy    |   500 |
|  2 | jackie   |  1000 |
|  3 | david    |  1500 |
|  4 | xiaoming |  2000 |
+----+----------+-------+
4 rows in set (0.00 sec)

終端2插入id為4的記錄,未插入成功,並陷入假死狀態。一段時間後爆出1205錯誤

##Centos7-1:2
mysql> insert into test_tb1 values (4,'xiaohong',1750);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

終端1提交事務。並檢視插入結果

##Centos7-1:1
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_tb1;
+----+----------+-------+
| id | name     | money |
+----+----------+-------+
|  1 | nancy    |   500 |
|  2 | jackie   |  1000 |
|  3 | david    |  1500 |
|  4 | xiaoming |  2000 |
+----+----------+-------+
4 rows in set (0.00 sec)

4.1.3 預設級別中記錄的修改

終端1開始一個事務,修改nancy的money值為750。

##Centos7-1:1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test_tb1 set money=750 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from test_tb1;
+----+----------+-------+
| id | name     | money |
+----+----------+-------+
|  1 | nancy    |   750 |
|  2 | jackie   |  1000 |
|  3 | david    |  1500 |
|  4 | xiaoming |  2000 |
+----+----------+-------+
4 rows in set (0.00 sec)

終端2,將nancy的money值修改為650。無法修改,並顯示鎖等待時間超時。

##Centos7-1:2
mysql> select * from test_tb1;
+----+----------+-------+
| id | name     | money |
+----+----------+-------+
|  1 | nancy    |   500 |
|  2 | jackie   |  1000 |
|  3 | david    |  1500 |
|  4 | xiaoming |  2000 |
+----+----------+-------+
4 rows in set (0.00 sec)

mysql> update test_tb1 set money=650 where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

將jackie的money值修改為1250。正常修改。

##Centos7-1:2
mysql> update test_tb1 set money=1250 where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

4.1.4 總結

在mysql預設隔離級別RR進行操作的時候,當事務對一行記錄進行操作的時候,對該行記錄會進行鎖定,防止其他事務對該記錄修改,從而導致記錄的混亂,且在一個事務當中,僅能夠看見自己事務中對錶記錄修改的狀態,無法檢視其他事務提交的修改結果。