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.
[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)
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
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)
2. Ketekalan
3. Pengasingan
4. Ketahanan
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 保存点; -- 回滚到某个保存点 (这个后面就不测试,知道有这个操作就行)
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)
< . > 3. Mod transaksi eksplisit 2
-- 看下当前autocommit的状态是,默认是on状态 mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.01 sec) -- 插入一条数据 mysql> insert into ajisun values(1,'阿纪'); 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)
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,'纪先生'); 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)
-- 插入一条数据 mysql> insert into ajisun values(2,'ajisun'); 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)
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)
-- 开启事务 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)
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 berulangTransaksi 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 标准定义了四个隔离级别:
脏读
、不可重复读
和幻读
。但是并发度最高幻读
和不可重复读
仍有可能发生。脏读
和不可重复读
,但幻读
仍有可能发生。脏读
、不可重复读
以及幻读
。并发度也是最低的MySQL默认采用的 REPEATABLE_READ 隔离级别 Oracle默认采用的 READ_COMMITTED 隔离级别
1. 如何设置隔离级别
可以通过变量参数transaction_isolation
查看隔离级别
mysql> SELECT @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | REPEATABLE-READ | +-------------------------+ 1 row in set (0.00 sec) mysql> show variables like '%transaction_isolation%'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ | transaction_isolation | REPEATABLE-READ | +-----------------------+-----------------+ 1 row in set (0.02 sec)
修改的命令:SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL $[level];
level的值就是4中隔离级别READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE
设置全局隔离级别
只对执行完该语句之后产生的会话起作用。
当前已经存在的会话无效。
set global transaction_isolation='read-uncommitted'; set global transaction_isolation='read-committed'; set global transaction_isolation='repeatable-read'; set global transaction_isolation='serializable';
例如:
会话A
mysql> set global transaction_isolation='serializable'; 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)
会话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)
设置会话的隔离级别
对当前会话的所有后续的事务有效
该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务。
如果在事务之间执行,则对后续的事务有效。
set session transaction_isolation='read-uncommitted'; set session transaction_isolation='read-committed'; set session transaction_isolation='repeatable-read'; set session transaction_isolation='serializable';
比如:
会话A
mysql> set session transaction_isolation='read-uncommitted'; Query OK, 0 rows affected (0.00 sec) mysql> select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | READ-UNCOMMITTED | +-------------------------+ 1 row in set (0.00 sec)
新建会话B(依然是默认的级别:可重复读)
mysql> select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | REPEATABLE-READ | +-------------------------+ 1 row in set (0.00 sec)
2. 怎么选择隔离级别
一般情况下默认的可重复读
就好了,一般很少改这个,除非业务场景特殊
记住一点:隔离级别越高,并发问题就越少,但并发性也就越低,所以还是要根据业务选择来。
六. 总结
事务的四大特性:原子性,一致性,隔离性,持久性
事务的常见命令:
set autocommit=0/1; -- 关闭/开启自动提交事务 start transaction; -- 开启事务(或者用begin) rollback; -- 回滚事务 commit; -- 提交事务
并发事务的问题:脏写 > 脏读 > 不可重复读 > 幻读
需要熟悉事务的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!