【0928 | Day 39】事务(精讲)

一、事务

在mysql中,事务其实是一个最小的不可分割的工作单元,事务能够保证一个业务的完整性

比如我们的银行转账:
   a给b转100块钱,相当于
   update user set monry=money-100 where name='a'
update user set monry=money+100 where name='b'

需要两条语句,在实际情况中,如果只有一条语句执行成功,而另一条没有执行成功,就会出现数据前后不一致的情况。

事务用来解决:多条sql语句可能会有同时成功的要求,要么就同时失败。

1. mysql如何控制事务?

mysql默认是自动提交的

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.52 sec)

2. 默认事务开启的作用是什么?

  • 当我们去执行一个sql语句的时候,效果会立即体现出来,且不能回滚。
  • 这里又出现了一些概念(回滚),我们举例来说:
  • 创建一个数据库,再创建数据表,插入数据
mysql> create database bank;
Query OK, 1 row affected (0.64 sec)

mysql> use bank;
Database changed

mysql> create table user(
    -> id int primary key,
    -> name varchar(20),
    -> money int
    -> );
Query OK, 0 rows affected (0.93 sec)
mysql> insert into user values(1,'a',1000);
Query OK, 1 row affected (0.51 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+
1 row in set (0.00 sec)

事务回滚:撤销sql的执行效果 (rollback;)

下面调用rollback

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+
1 row in set (0.00 sec)

可以看到,即使调用了rollback,数据依然存在,说明是不能够回滚的,添加数据的语句执行完后默认就提交了。

我们可以通过设置默认事务为0的方式来进行改变,也就是设置mysql默认提交为falseset autocommit=0;(1为开启,0为关闭)

mysql> set autocommit=0;
Query OK, 0 rows affected (0.54 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)

上面的操作,关闭了mysql的自动提交(commit)

这里在操作一遍来验证:(这时候自动提交已经关闭了)

mysql> insert into user values(2,'b',1000); #插入数据
Query OK, 1 row affected (0.00 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

mysql> rollback;  #进行回滚
Query OK, 0 rows affected (0.07 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+
1 row in set (0.00 sec)

惊不惊喜,刚才插入的数据没有了。我们在执行完语句时(关闭默认提交),看到的效果只是一个临时效果,并没有真实的发生在我们数据库里面,是在一张虚拟的表中。

这里可以用commit提交

#再插入一次数据
mysql> insert into user values(2,'b',1000);
Query OK, 1 row affected (0.00 sec)

#手动提交数据
mysql> commit;
Query OK, 0 rows affected (0.15 sec)

#再撤销,是不可以撤销的(事务的一个特性:持久性)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

只要commit了,rollback也没有用了,持久哦~

自动提交: @@autocommit=1

手动提交: commit

回滚: rollback(在没有提交的情况下,是可以提交的)

也就是说,事务给我们提供了一个返回的机会!!!

就像前面说的,当发现有一条语句没有执行成功的情况下,可以回滚了。在检查无误之后,再手动commit让它生效,产生真实效果。

我们再把事务关闭,改为自动提交:

mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

3. 事务的其他打开方式?

手动开启事务:begin或者 start transaction,都可以帮我们手动开启一个事务

这里进行转账例子:

mysql> update user set money=money-100 where name='a';
Query OK, 1 row affected (0.95 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update user set money=money+100 where name='b';
Query OK, 1 row affected (0.14 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)

#事务回滚
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)

这里发现现在rollback是没有任何效果的,因为现在autocommit=1,为自动提交模式,每当执行一句话就立即生效了。

现在在输入这两个语句之前,输入begin或者 start transaction

#加上begin;或者 start transaction 开启事务
mysql> begin;
Query OK, 0 rows affected (0.01 sec)

#对a、b进行转账操作
mysql>  update user set money=money-100 where name='a';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> update user set money=money+100 where name='b';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

#看一下表
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   800 |
|  2 | b    |  1200 |
+----+------+-------+
2 rows in set (0.00 sec)

#事务回滚
mysql> rollback;
Query OK, 0 rows affected (0.57 sec)

mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)

事务开启后,一旦 commit 提交,就不可回滚(也就是这个事务在提交的时候结束了),此时再rollback也没有用了

二、事物的四大特性

1. 原子性

  • 事务是一组不可分割的单位,要么同时成功,要么同时不成功

2. 一致性

  • 事物前后的数据完整性应该保持一致(数据库的完整性:如果数据库在某一时间点下,所有的数据都符合所有的约束,则称数据库为完整性的状态)

3. 隔离性

  • 事物的隔离性是指多个用户并发访问数据时,一个用户的事物不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离

4. 持久性

  • 持久性是指一个事物一旦被提交,它对数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
原文地址:https://www.cnblogs.com/fxyadela/p/11605151.html