亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

MySQL 事務(wù)

asal 2016-11-07 15:23:32 667
abstrak:簡介事務(wù)是一組原子性的 SQL 查詢, 或者說是一個獨立的工作單元. 在事務(wù)內(nèi)的語句, 要么全部執(zhí)行成功, 要么全部執(zhí)行失敗.事務(wù)的 ACID 性質(zhì)數(shù)據(jù)庫事務(wù)擁有以下四個特性, 即 ACID 性質(zhì):原子性(Atomicity): 事務(wù)作為一個整體被執(zhí)行, 包含在其中的對數(shù)據(jù)庫的操作要么全部執(zhí)行成功, 要么全部失敗回滾. 對于一個事務(wù)來說, 不可能只執(zhí)行其中一部分操作, 這就是事務(wù)的原子性.一致性(

簡介

事務(wù)是一組原子性的 SQL 查詢, 或者說是一個獨立的工作單元. 在事務(wù)內(nèi)的語句, 要么全部執(zhí)行成功, 要么全部執(zhí)行失敗.

事務(wù)的 ACID 性質(zhì)

數(shù)據(jù)庫事務(wù)擁有以下四個特性, 即 ACID 性質(zhì):

  • 原子性(Atomicity): 事務(wù)作為一個整體被執(zhí)行, 包含在其中的對數(shù)據(jù)庫的操作要么全部執(zhí)行成功, 要么全部失敗回滾. 對于一個事務(wù)來說, 不可能只執(zhí)行其中一部分操作, 這就是事務(wù)的原子性.

  • 一致性(Consistency): 事務(wù)應(yīng)確保數(shù)據(jù)庫的狀態(tài)從一個一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€一致狀態(tài).

  • 隔離性(Isolation): 多個事務(wù)并發(fā)執(zhí)行時, 一個事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行.

  • 持久性(Durability): 已被提交的事務(wù)對數(shù)據(jù)庫的修改應(yīng)該永久保存在數(shù)據(jù)庫中.

事務(wù)的隔離級別

SQL 中定義了四種隔離級別, 每種級別都規(guī)定了一個事務(wù)所做的修改,哪些在事務(wù)內(nèi)和事務(wù)間是可見的, 哪些是不可見的. 較低的隔離通??梢詧?zhí)行更高的并發(fā), 系統(tǒng)的開銷也更低.

SQL 標(biāo)準(zhǔn)中的四種隔離有:

  • READ UNCOMMITED(未提交讀)

在 READ UNCOMMITED 級別中, 事務(wù)的修改, 即使沒有提交, 對其他事務(wù)也是可見的. 其他事務(wù)可以讀取此事務(wù)中的未提交的數(shù)據(jù), 這也被稱為臟讀(Dirty Read). 此事務(wù)隔離級別會導(dǎo)致很多問題, 并且性能也不會比其他事務(wù)隔離級別好多少, 因此在實際環(huán)境中很少使用.

  • READ COMMITED(提交讀)

大多數(shù)的數(shù)據(jù)庫默認(rèn)隔離級別都是 READ COMMITED, 但是 MySQL 并不是. 在 READ COMMITED 級別中, 一個事務(wù)從開始到提交之前, 所做的任何修改對其他事務(wù)都是不可見的.

這個級別有時候也叫做不可重復(fù)讀(nonrepeatable read), 因為兩次執(zhí)行相同的查詢, 可能會得到不一樣的結(jié)果.

  • REPEATABLE READ(可重復(fù)讀)

REPEATABLE READ 解決了臟讀的問題. 該級別保證了在同一個事務(wù)中多次讀取同樣記錄的結(jié)果時一致的. 但是理論上, 可重復(fù)讀隔離級別還是無法解決另一個幻讀(Phantom Read)的問題. 所謂幻讀, 指的是當(dāng)某個事務(wù)在讀取某個范圍內(nèi)的記錄時, 另外一個事務(wù)又在該范圍內(nèi)插入了新的記錄, 當(dāng)之前的事務(wù)再次讀取該范圍的記錄時, 會產(chǎn)生幻行(Phantom Row).

可重復(fù)讀是 MySQL 的默認(rèn)事務(wù)隔離級別.

  • SERIALIZABLE(可串行化)

SERIALIZABLE 是最高的隔離級別. 他通過強制事務(wù)串行執(zhí)行, 避免了前面說的幻讀的問題. 簡單來說, SERIALIZABLE 會在讀取的每一行數(shù)據(jù)上都加上鎖, 所以可能導(dǎo)致大量的超時和鎖爭用的問題. 實際應(yīng)用中也很少用到這個隔離級別, 只有在非常需要確保數(shù)據(jù)的一致性而且可以接受沒有并發(fā)的情況下, 才考慮采用該級別.

死鎖

死鎖是指兩個或多個事務(wù)在同一個資源上相互占用, 并請求鎖定對方占用的資源, 從而導(dǎo)致惡性循環(huán)的現(xiàn)象. 當(dāng)多個事務(wù)試圖以不同順序鎖定資源時, 就可能產(chǎn)生死鎖.

死鎖發(fā)生以后, 只有部分或者完全回滾其中一個事務(wù), 才能打破死鎖.

MySQL 中的事務(wù)

在 MySQL 提供的眾多存儲引擎中, 只有 InnoDB 和 NDB Cluster 支持事務(wù).

關(guān)于自動提交(AUTOCOMMIT)

MySQL 默認(rèn)采用自動提交(AUTOCOMMIT) 模式. 即如果不顯示地開始一個事務(wù), 則每個操作都被當(dāng)做一個事務(wù)執(zhí)行提交操作.

我們可以通過

SHOW VARIABLES LIKE 'autocommit';

查詢當(dāng)前是否已經(jīng)開啟了字段提交事務(wù), 例如:

mysql> SHOW VARIABLES LIKE 'autocommit';

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

| Variable_name | Value |

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

| autocommit    | ON    |

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

1 row in set (0.00 sec)

如果是 ON, 則表示已經(jīng)開啟了, 0 或 OFF 表示禁用.

可以通過 "set autocommit=0;" 來禁用自動提交:

set autocommit=0;

對于非事務(wù)型存儲引擎, 例如 MyISAM, 修改 AUTOCOMMIT 屬性試不會有影響的.

自動提交和非自動提交的區(qū)別

下面以一個例子來展示 autocommit 啟動和非啟動時的區(qū)別.

首先建立一個測試用的表:

CREATE TABLE `user` (

  `id`   BIGINT(20) NOT NULL AUTO_INCREMENT,

  `name` VARCHAR(20)         DEFAULT '',

  `age`  INT(11)             DEFAULT '0',

  PRIMARY KEY (`id`)

)

  ENGINE = InnoDB

  DEFAULT CHARSET = utf8mb4

接著關(guān)閉自動提交功能:

mysql> set autocommit=0;

然后插入一個數(shù)據(jù):

mysql> INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);

接著查看數(shù)據(jù):

mysql> select * from user;

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

| id | name | age  |

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

|  1 | xys  |   18 |

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

1 row in set (0.00 sec)

數(shù)據(jù)庫中可以查詢到這條數(shù)據(jù)了.

但是我們通過 SHOW BINLOG EVENTS 查看操作日志:

mysql> show binlog events;

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

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

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

| mysql-bin.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.13-log, Binlog ver: 4 |

| mysql-bin.000001 | 123 | Previous_gtids |         1 |         154 |                                       |

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

2 rows in set (0.00 sec)

會發(fā)現(xiàn)上面的輸出中, 并沒有插入數(shù)據(jù)相關(guān)的記錄, 并且此時如果我們退出 MySQL 的話, 那么我們插入的數(shù)據(jù)并沒有被保存:

mysql> exit

Bye

>>> mysql -u root -p

Enter password:

mysql> use test;

Database changed

mysql> select * from user;

Empty set (0.00 sec)

mysql>

如果我們不退出, 而是輸入COMMIT; 時, 那么此時數(shù)據(jù)才真正保存到 MySQL 中:

mysql> commit;

Query OK, 0 rows affected (0.02 sec)

mysql> show binlog events;

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

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

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

| mysql-bin.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.13-log, Binlog ver: 4 |

| mysql-bin.000001 | 123 | Previous_gtids |         1 |         154 |                                       |

| mysql-bin.000001 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |

| mysql-bin.000001 | 219 | Query          |         1 |         291 | BEGIN                                 |

| mysql-bin.000001 | 291 | Table_map      |         1 |         342 | table_id: 108 (test.user)             |

| mysql-bin.000001 | 342 | Write_rows     |         1 |         394 | table_id: 108 flags: STMT_END_F       |

| mysql-bin.000001 | 394 | Xid            |         1 |         425 | COMMIT /* xid=58 */                   |

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

7 rows in set (0.00 sec)

從上面的操作中我們可以看到, 當(dāng)禁用了 AUTOCOMMIT 后, 我們對數(shù)據(jù)庫的寫入操作并不會實際落地到數(shù)據(jù)庫中, 除非我們顯示地提交事務(wù).

接下來, 我們使能 AUTOCOMMIT, 再次進行相同的操作.

mysql> set autocommit=1;

mysql> SHOW VARIABLES LIKE 'autocommit';

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

| Variable_name | Value |

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

| autocommit    | ON    |

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

1 row in set (0.00 sec)

然后插入一個數(shù)據(jù):

mysql> INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);

接著查看數(shù)據(jù):

mysql> select * from user;

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

| id | name | age  |

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

|  1 | xys  |   18 |

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

1 row in set (0.00 sec)

數(shù)據(jù)庫中可以查詢到這條數(shù)據(jù)了.

我們再次查看 binlog, 對比一下和禁用 AUTOCOMMIT 時有什么差別:

mysql> show binlog events;

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

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

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

| mysql-bin.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.13-log, Binlog ver: 4 |

| mysql-bin.000001 | 123 | Previous_gtids |         1 |         154 |                                       |

| mysql-bin.000001 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |

| mysql-bin.000001 | 219 | Query          |         1 |         291 | BEGIN                                 |

| mysql-bin.000001 | 291 | Table_map      |         1 |         342 | table_id: 108 (test.user)             |

| mysql-bin.000001 | 342 | Write_rows     |         1 |         394 | table_id: 108 flags: STMT_END_F       |

| mysql-bin.000001 | 394 | Xid            |         1 |         425 | COMMIT /* xid=292 */                  |

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

7 rows in set (0.00 sec)

我們看到, 和禁用 AUTOCOMMIT 不同的是, 使能 AUTOCOMMIT 時, 每個寫操作都會進行事務(wù)的提交. 即上面的 insert 操作等效為:

BEGIN;

INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);

COMMIT;


Nota Keluaran

Penyertaan Popular