事务

事务管理
1、事务的概念
事务就是针对数据库的一组操作,它可以由一条或多条SQL语句组成,同一个事务的操作具备同步的特点,如果其中有一条语句无法执行,那么所有的语句都不会执行,也就是说,事务中的语句要么都执行,要么都不执行。
开启事务: START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
(注意:ROLLBACK语句只能针对未提交的事务执行回滚操作,已提交的事务是不能回滚的。)

实例如下:
首先需要创建一个名称为cp06的数据库,并且在cp06中创建一个account1表,插入相应的数据
mysql> CREATE DATABASE cp06;
Query OK, 1 row affected

mysql> USE cp06;
Database changed

mysql> CREATE TABLE account1(
-> id INT primary key auto_increment,
-> name VARCHAR(40),
-> money FLOAT
-> )ENGINE=InnoDB;
Query OK, 0 rows affected

mysql> INSERT INTO account1(name,money)VALUES('a',1000);
Query OK, 1 row affected

mysql> INSERT INTO account1(name,money)VALUES('b',1000);
Query OK, 1 row affected


首先开启一个事务,然后通过UPDATE语句将a账户的100元钱转给b账户,最后提交事务
mysql> START TRANSACTION;
Query OK, 0 rows affected

mysql> UPDATE account1 SET money=money-100 WHERE NAME='a';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0

mysql> UPDATE account1 SET money=money+100 WHERE NAME='b';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected

查询:
mysql> SELECT * FROM account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set


事务的四大特性
(1)原子性(Atomicity) :指一个事务必须被视为一个不可分割的最小工作单元,只有事务中所有的数据库操作都执行成功,才算整个事务执行成功,事务中如果有任何一个SQL语句执行失败,已经执行成功的SQL语句也必须撤销,数据库的状态退回到执行事务前的状态。

(2)一致性(Consistency)指事务将数据库从一种状态转变为下一种一致的状态。例如,在表中有一个字段为姓名,具有唯一约束,即姓名不能重复,如果一个事务对姓名进行了修改,使姓名变得不唯一了,这就破坏了事务的一致性要求,如果事务中的某个动作失败了,系统可以自动撤销事务,返回初始化的状态。

(3)隔离性(Isolation) 还可以称为并发控制、可串行化、锁等,当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
(4)持久性(Durability) 事务一旦提交,其所做的修改就会永久保存到数据库中,即使数据库发生故障也不应该对其有任何影响。需要注意的是,事务的持久性不能做到100%的持久,只能从事务本身的角度来保证永久性,而一些外部原因导致数据库发生故障,如硬盘损坏,那么所有提交的数据可能都会丢失。


2、事务的提交
在数据库中事务中的提交操作需要用户进行确认,当用户确认提交后,事务中的操作才会执行成功,这个过程就是手动提交的过程。为了说明事务的提交方式为手动提交,接下来,在account1的基础上进行操作,开启一个事务,使用UPDATE语句实现由b账户向a账户转100元钱的转账功能,具体操作如下:

(1)执行转账语句,不提交事务
mysql> START TRANSACTION;
Query OK, 0 rows affected
//开启事务

mysql> UPDATE account1 SET money=money+100 WHERE NAME='a';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0

mysql> UPDATE account1 SET money=money-100 WHERE NAME='b';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
//b账户向a账户转账100元
查看:
mysql> SELECT * FROM account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
2 rows in set
//在事务中实现 了转账功能
此时,退出数据库然后重新登录,并查询数据库中各账户的余额信息,查询结果如下:
mysql> select * from account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set
//事务中的转账操作没有成功
结论:在事务中转账成功后没有提交事务就退出了数据库,由于事务中的语句不能自动提交,因此当前的操作会被自动取消。


(2)执行转账语句,提交事务
mysql> START TRANSACTION;
Query OK, 0 rows affected
//开启事务

mysql> UPDATE account1 SET money=money+100 WHERE name='a';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0

mysql> UPDATE account1 SET money=money-100 WHERE name='b';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
//b账户向a账户转账100元

mysql> COMMIT;
Query OK, 0 rows affected
//提交事务

查看:
mysql> SELECT * FROM account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1100 |
| 2 | b | 900 |
+----+------+-------+
2 rows in set

上述语句执行成功后,退出数据库然后再重新登录,使用SELECT语句查询数据库中各账户的余额信息,查询结果如下:mysql> SELECT * FROM account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
2 rows in set
//实现了转账功能
结论:事务中的操作都是手动提交的,因此在操作完事务时,一定要使用COMMIT语句提交事务,否则事务操作会失败。


3、事务的回滚
在操作一个事务时,如果发现当前事务中的操作是不合理的,此时只要还没有提交事务,就可以通过回滚来取消当前事务。
为了演示事务的回滚操作,在2的基础上进行操作,这时的a账户有1000元,b账户有1000元,开启一个事务,通过update语句将a账户的100元钱转给b账户:
mysql> START TRANSACTION;
Query OK, 0 rows affected
//开启事务
mysql> UPDATE account1 SET money=money-100 WHERE name='a';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0

mysql> UPDATE account1 SET money=money+100 WHERE name='b';
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
//a账户向b账户转账100元

查看:
mysql> SELECT * FROM account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set
//转账成功

mysql> ROLLBACK;
Query OK, 0 rows affected
//回滚

再查看:
mysql> SELECT * FROM account1;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
2 rows in set
回滚操作成功,当前事务中的操作取消了


4、事务的隔离级别
数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样就会出现脏读、重复读以及幻读的情况,为了避免这种情况的发生,就需要为事务设置隔离级别。在MySQL中,事务有四种隔离级别。(1)READ UNCOMMITTED(读未提交)(2)READ COMMITTED(读提交)(3)REPEATABLE READ(可重复读)(4)SERIALIZABLE(可串行化)

posted @ 2019-12-26 11:28  余笙1035  阅读(239)  评论(0)    收藏  举报