Pemahaman mendalam tentang transaksi, 4 ciri utama dan tahap pengasingan dalam MySQL

青灯夜游
Lepaskan: 2021-10-14 13:39:45
ke hadapan
1797 orang telah melayarinya

Artikel ini ialah kajian lanjutan tentang MySQL Ia akan memberi anda pengenalan terperinci kepada transaksi dalam MySQL, empat ciri utama (ACID) dan tahap pengasingan transaksi saya harap ia akan membantu anda.

Pemahaman mendalam tentang transaksi, 4 ciri utama dan tahap pengasingan dalam MySQL

[Cadangan berkaitan: tutorial video mysql]

Versi persekitaran yang digunakan untuk pengendalian dan ujian artikel ini ialah 5.7.21

mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.21    |
+-----------+
1 row in set (0.00 sec)
Salin selepas log masuk

Ingat: Antara enjin storan MySQL biasa kami, hanya InnoDB yang menyokong transaksi. Oleh itu, operasi berikut juga dilakukan di bawah InnoDB.

1 Apakah itu urus niaga

Transaksi ialah operasi logik yang disarikan daripada realiti, sama ada semuanya dilaksanakan atau tiada Perlaksanaan , tidak boleh ada pelaksanaan separa.

Kes yang lebih klasik ialah pindahan bank: Little A memindahkan 100 yuan kepada Little B

Situasi biasa: Akaun Little A ditolak sebanyak 100 yuan, dan akaun Little B dinaikkan sebanyak 100 yuan.

Situasi tidak normal: Akaun Little A ditolak sebanyak 100 yuan, dan jumlah dalam akaun Little B kekal tidak berubah.

Dalam keadaan luar biasa, terdapat masalah dengan sistem perbankan selepas 100 yuan ditolak daripada akaun Little A, dan operasi menambah 100 yuan ke akaun Little B tidak dilaksanakan. Maksudnya, jumlah di kedua-dua belah pihak tidak sepadan dengan Little A tidak bersedia, Little B tidak bersedia, dan begitu juga dengan bank. Tujuan urusan adalah untuk mengelakkan situasi yang tidak normal dan memuaskan hati semua orang.

2. 4 ciri utama urus niaga (ACID)

1 operasi tidak boleh dibahagikan, sama ada semua operasi atau tiada, sama seperti pemindahan, tiada keadaan perantaraan. Dan atomicity ini tidak bermakna hanya ada satu tindakan, mungkin terdapat banyak operasi, tetapi ia tidak dapat dipisahkan daripada hasilnya, yang bermaksud bahawa atomicity adalah keadaan hasil.

2. Ketekalan

Sebelum dan selepas melaksanakan transaksi, data kekal konsisten, sama seperti sistem akaun bank Tidak kira sama ada transaksi berjaya atau tidak. jumlah akaun kedua-duanya Ia sepatutnya sama.

3. Pengasingan

Apabila berbilang transaksi mengendalikan data pada masa yang sama, berbilang transaksi diasingkan secara langsung antara satu sama lain dan tidak akan menjejaskan satu sama lain.

4. Ketahanan

Kesan transaksi pada data selepas penyerahan adalah kekal dan tidak akan hilang apabila ditulis ke cakera.

3. Urus niaga eksplisit dan urus niaga tersirat

Transaksi MySQL dibahagikan kepada dan

Transaksi lalai ialah transaksi Tersirat dimulakan secara automatik, diserahkan dan digulung semula oleh pembolehubah

semasa operasi. 显式事务隐式事务Arahan utama yang dikawal adalah seperti berikutautocommit

Mula-mula buat jadual ajisun

set autocommit=0; -- 关闭自动提交事务(显式)
set autocommit=1; -- 开启自动提交事务(隐式)
  -- 当autocommit=0的时候手动控制事务
rollback; -- 回滚事务
commit;  -- 提交事务
-- 当autocommit=1 自动提交事务,但是可以控制手动提交
start transaction; -- 开启事务(或者用begin开启事务)
commit; -- 提交事务
rollback; -- 回滚事务
SAVEPOINT 保存点名称;  -- 保存点(相当于存档,可以不用回滚全部操作)
rollback to  保存点;  -- 回滚到某个保存点 (这个后面就不测试,知道有这个操作就行)
Salin selepas log masuk

1 Transaksi tersirat
mysql> create table ajisun(id int(5), name varchar(20) character set utf8  COLLATE utf8_bin ) engine=innodb character set= utf8mb4 COLLATE = utf8mb4_bin;
Query OK, 0 rows affected (0.03 sec)
Salin selepas log masuk

< . > 3. Mod transaksi eksplisit 2

-- 看下当前autocommit的状态是,默认是on状态
mysql> show variables like &#39;autocommit&#39;; 
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.01 sec)

--  插入一条数据
mysql> insert into ajisun values(1,&#39;阿纪&#39;);
Query OK, 1 row affected (0.00 sec)
mysql> rollback;

-- 执行rollback 也是没有效果的,还是能够查询到插入的数据(不需要我们手动控制commit)
mysql> select * from ajisun;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 阿纪   |
+------+--------+
1 row in set (0.00 sec)
Salin selepas log masuk

Gunakan mulakan transaksi untuk menukar kepada transaksi lalai dahulu

-- 开启显式事务-回滚
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from ajisun;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 阿纪   |
+------+--------+
1 row in set (0.00 sec)

mysql> insert into ajisun values(2,&#39;纪先生&#39;);
Query OK, 1 row affected (0.00 sec)
-- 插入后可以看见2条数据
mysql> select * from ajisun;
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | 阿纪      |
|    2 | 纪先生    |
+------+-----------+
2 rows in set (0.00 sec)
-- 回滚之后上面插入的数据就没了
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from ajisun;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 阿纪   |
+------+--------+
1 row in set (0.00 sec)
Salin selepas log masuk
-- 插入一条数据
mysql> insert into ajisun values(2,&#39;ajisun&#39;);
Query OK, 1 row affected (0.01 sec)
-- 提交
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
-- 回滚
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
-- 先提交commit,在rollback 数据依然存在,说明commit生效,事务已提交,回滚就不生效了。
mysql> select * from ajisun;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 阿纪   |
|    2 | ajisun |
+------+--------+
2 rows in set (0.00 sec)
Salin selepas log masuk

4 Masalah dalam urus niaga serentak

Jika hanya ada satu transaksi yang beroperasi di atas meja pada masa yang sama, tidak akan ada masalah, tetapi ini adalah mustahil. Pada hakikatnya, ia digunakan sebanyak mungkin, dan berbilang transaksi dikendalikan pada masa yang sama. Berbilang transaksi akan menyebabkan banyak masalah, seperti

, set autocommit=1;,

,
-- 开启事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from ajisun where id=1;
Query OK, 1 row affected (0.00 sec)
-- 提交事务
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from ajisun;
+------+--------+
| id   | name   |
+------+--------+
|    2 | ajisun |
+------+--------+
1 row in set (0.00 sec)
Salin selepas log masuk
-- 开启事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from ajisun where id =2;
Query OK, 1 row affected (0.01 sec)
-- 回滚事务
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
-- 删除操作失效了
mysql> select * from ajisun;
+------+--------+
| id   | name   |
+------+--------+
|    2 | ajisun |
+------+--------+
1 row in set (0.00 sec)
Salin selepas log masuk

1. Bacaan kotor

A urus niaga membaca data yang diubah suai daripada urus niaga tidak komited lain Ini adalah bacaan yang kotor.

脏读脏写Sebagai contoh, dua transaksi a dan b: mengendalikan rekod pada masa yang sama `不可重复读幻读Selepas transaksi a mengubah suai rekod, ia belum diserahkan secara rasmi kepada pangkalan data masa, transaksi b membacanya, dan kemudian menggunakan baca Data yang diperoleh digunakan untuk operasi seterusnya.

Jika transaksi a ditarik balik dan data yang diubah suai tidak lagi wujud, maka transaksi b menggunakan data yang tidak wujud. Ini adalah data yang kotor.

2. Tulisan kotor (kehilangan data)

Transaksi mengubah suai data yang diubah suai oleh transaksi tanpa komitmen lain

Sebagai contoh, dua transaksi a dan b: mengendalikan rekod pada masa yang sama

Transaksi tidak diserahkan selepas pengubahsuaian, maka transaksi b juga mengubah suai data yang sama, dan kemudian transaksi b melakukan data.

Jika transaksi a melancarkan pengubahsuaiannya sendiri dan juga melancarkan semula pengubahsuaian transaksi b, masalahnya ialah: transaksi b telah diubah suai dan diserahkan, tetapi pangkalan data tidak berubah Keadaan ini adalah penulisan Kotor.

3. Bacaan tidak boleh berulang

Transaksi hanya boleh membaca data yang diubah suai oleh transaksi lain yang telah diserahkan dan transaksi lain tidak boleh membaca data . Selepas pengubahsuaian dibuat dan diserahkan, transaksi boleh ditanya untuk mendapatkan nilai terkini.

也就是在同一个事务中多次读取同一条记录,得到的内容都不一样(在每次读取之前都有其他事务完成修改并提交),这就是不可重复读

4. 幻读

在一个事务内 相同条件查询数据,先后查询到的记录数不一样

也就是一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来,那就意味着发生了幻读

不可重复读和幻读的区别:不可重复读重点在于同一条记录前后数据值不一样(内容的变化),而幻读重点在于相同查询条件前后所获取的记录数不一样(条数的变化)

五. 事务的隔离级别

上面说的事务的并发问题,在不同的场景下要求不一样,能接受的问题也不一样。他们之间的严重性排序如下:

脏写 > 脏读 > 不可重复读 > 幻读

MySQL中提供了4种隔离级别来处理这几个问题,如下

隔离级别脏读不可重复读幻影读
READ- UNCOMMITTED
READ-COMMITTED×
REPEATABLE-READ××
SERIALIZABLE×××

SQL 标准定义了四个隔离级别:

  • READ-UNCOMMITTED(读未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读不可重复读幻读。但是并发度最高
  • READ-COMMITTED(读已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读不可重复读仍有可能发生。
  • REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读不可重复读,但幻读仍有可能发生。
  • SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,该级别可以防止脏读不可重复读以及幻读。并发度也是最低的
MySQL默认采用的 REPEATABLE_READ 隔离级别 
Oracle默认采用的 READ_COMMITTED 隔离级别
Salin selepas log masuk

1. 如何设置隔离级别

可以通过变量参数transaction_isolation 查看隔离级别

mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)

mysql> show variables like &#39;%transaction_isolation%&#39;;
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.02 sec)
Salin selepas log masuk

修改的命令:SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL $[level];

level的值就是4中隔离级别READ-UNCOMMITTED READ-COMMITTED REPEATABLE-READ SERIALIZABLE

设置全局隔离级别

只对执行完该语句之后产生的会话起作用。

当前已经存在的会话无效。

set global transaction_isolation=&#39;read-uncommitted&#39;;
set global transaction_isolation=&#39;read-committed&#39;;
set global transaction_isolation=&#39;repeatable-read&#39;;
set global transaction_isolation=&#39;serializable&#39;;
Salin selepas log masuk

例如:

会话A

mysql> set global transaction_isolation=&#39;serializable&#39;;
Query OK, 0 rows affected (0.01 sec)
mysql> select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| SERIALIZABLE                   |
+--------------------------------+
1 row in set (0.00 sec)
-- 当前会话(设置之前就已经存在的会,级别是默认的)
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)
Salin selepas log masuk

会话B(set之后新建的会话)

mysql> select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| SERIALIZABLE                   |
+--------------------------------+
1 row in set (0.00 sec)

mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| SERIALIZABLE            |
+-------------------------+
1 row in set (0.00 sec)
Salin selepas log masuk

设置会话的隔离级别

对当前会话的所有后续的事务有效

该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务。

如果在事务之间执行,则对后续的事务有效。

set session transaction_isolation=&#39;read-uncommitted&#39;;
set session transaction_isolation=&#39;read-committed&#39;;
set session transaction_isolation=&#39;repeatable-read&#39;;
set session transaction_isolation=&#39;serializable&#39;;
Salin selepas log masuk

比如:

会话A

mysql> set session transaction_isolation=&#39;read-uncommitted&#39;;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-UNCOMMITTED        |
+-------------------------+
1 row in set (0.00 sec)
Salin selepas log masuk

新建会话B(依然是默认的级别:可重复读)

mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)
Salin selepas log masuk

2. 怎么选择隔离级别

一般情况下默认的可重复读就好了,一般很少改这个,除非业务场景特殊

记住一点:隔离级别越高,并发问题就越少,但并发性也就越低,所以还是要根据业务选择来。

六. 总结

  • 事务的四大特性:原子性,一致性,隔离性,持久性

  • 事务的常见命令:

    set autocommit=0/1; -- 关闭/开启自动提交事务
    start transaction; -- 开启事务(或者用begin)
    rollback; -- 回滚事务
    commit; -- 提交事务
    Salin selepas log masuk
  • 并发事务的问题:脏写 > 脏读 > 不可重复读 > 幻读

  • 需要熟悉事务的4种隔离级别以及MySQL默认级别

  • 怎么设置隔离级别(global,session)

  • 更多编程相关知识,请访问:编程入门!!

    Atas ialah kandungan terperinci Pemahaman mendalam tentang transaksi, 4 ciri utama dan tahap pengasingan dalam MySQL. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!