欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL事务,事务的四大特性以及四种隔离级别

程序员文章站 2022-05-09 15:13:39
...

事务是sql业务中最小的不可分割的单元,一个事务中的多条sql语句,要么同时成功,要么同时失败。
mysql默认,autocommit=1,也就是每条sql语句作为一个事务并自动提交。
事务的三种操作:
自动提交:

//mysql默认是开启事务的,当执行sql语句的时候,自动提交,效果立现,且不能回滚,即撤销。
select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+

手动提交和事务回滚:
一条指令写进去,没有跟着commit的话,是不会提交到真正的表里,通过select可以看到一个虚拟的操作效果。
执行commit之后,将事务提交,一旦提交,不能撤销。
或者是执行rollback,将事务回滚,事务内的sql语句全部撤销。

set autocommit=0;//可以设置autocommit为0,取消自动提交,就可以通过回滚,撤销事务。
rollback;//没有commit的时候,使用rollback可以回滚。
commit;//提交之后,使用rollback也不能回滚。

手动提交的两种方法:
(1)begin+commit/rollback
(2)start transaction

//手动开启一个事务的方法begin或者start transacton
begin;
update...;
update...;
//在执行语句之前加上begin,可以手动开启一个事务,本事务可以回滚。
//begin开启的事务可以通过rollback进行回滚,或者使用commit进行提交。
start transaction;
updata...;
update...;
//同样使用rollback回滚或使用commit进行提交。

事务的四大特征:ACID

A:原子性:事务是不可分割的最小单位
C:一致性:要求事务中的sql语句同时成功或同时失败
I:隔离性:事务1和事务2之间互相隔离,具体有四种隔离性
D:持久性:事务一旦结束(commit、rollback)之后,不能撤销。

四种隔离级别;
read uncommitted(读未提交)
read committed(读已提交)
repeatable read(可重复读)
serializable(串行化)
查看系统隔离级别:以下三种方式,加了global指全局隔离级别,一般设置隔离级别就是设置全局隔离级别,而非设置事务的隔离级别。

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+


mysql> select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ                |
+--------------------------------+

(1)设置隔离级别为read uncommitted
一个事务修改但未commit的数据,另一个事务可以看到。

set autocommit=0;
mysql> select * from score where ke_num=1;
+------+--------+-------+
| num  | ke_num | score |
+------+--------+-------+
| 2001 |      1 |    93 |
| 2007 |      1 |    58 |
| 2005 |      1 |    87 |
+------+--------+-------+
begin;
update score set score =100 where num=2001;//此时另一个地方,可以读到修改后的数据100
rollback;//另一个地方没有重新读,就会默认读到了刚才读到的数据
//当然,如果重新读,也可以再看到撤销后的数据
//这样的问题就是,随时修改随时能查看到,究竟哪一次是准确的呢

所以read uncommitted容易出现脏读的问题。
(2)read committed可以解决脏读的问题,因为只有一个事务commit之后,另一个事务才能读到修改后的数据。而且commit之后是无法撤销的,因此不会有脏读问题。

set global transaction isolation level read committed;
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-COMMITTED        |
+-----------------------+
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
mysql> begin;

mysql> update score set score=100 where num=2004;
//在提交之前,另一个事务读不到修改后的数据,只有commit之后才能读到。
mysql> commit;
//会导致在一个事务中,前后两次读到的数据不一致。

因此read committed会出现不可重复读问题。
(3)repeatable read(可重复读)

set global transaction isolation level repeatable read;
select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+

两个地方开启了两个事务,一个事务对数据表进行insert、delete和update等操作,提交之后,另一个事务也看不到修改。修改前的数据是可重复读的。
如下图,右边的事务插入一条数据8,但左边的事务查看表单的时候,没有8的显示。
MySQL事务,事务的四大特性以及四种隔离级别
这种情况下可能会产生幻读。如下图,再向表中添加数据8时,显示8这条记录已经存在了。
MySQL事务,事务的四大特性以及四种隔离级别
(4)第四种隔离级别——serializable串行化

set global transaction isolation level serializable;
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| SERIALIZABLE          |
+-----------------------+

串行化的效果是,如果其中一个事务在修改数据表,那么另一个事务也要修改数据表,则sql语句卡住进入等待状态,只有前一个事务commit之后,才能进行修改,不过select 语句可以执行。
从下面这个图可以看出,左边的事务insert未提交,右边对同一个数据表进行insert,则会原地等待。
MySQL事务,事务的四大特性以及四种隔离级别
当前一个事务commit之后,后一个事务将会执行操作,并判断是否合理性操作。
MySQL事务,事务的四大特性以及四种隔离级别
串行化对不同的数据表进行操作时,互不影响。
MySQL事务,事务的四大特性以及四种隔离级别
四种隔离级别,级别越高,出现的脏读、不可重复读和幻读的问题越少,但是性能也越差,MySQL默认的隔离级别是repeatable read。

相关标签: MySQL