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

事务是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的显示。
在这里插入图片描述
这种情况下可能会产生幻读。如下图,再向表中添加数据8时,显示8这条记录已经存在了。
在这里插入图片描述
(4)第四种隔离级别——serializable串行化

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

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

原创文章 64 获赞 27 访问量 9414

猜你喜欢

转载自blog.csdn.net/weixin_44893585/article/details/104673730