一、事务
在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. 持久性
- 持久性是指一个事物一旦被提交,它对数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响