一、 事务特性
说到事务不得不提一下事务的特性:原子性、一致性、隔离性、持久性。下面是个人对这4个特性的理解:
原子性:
所谓的原子性就是事务不可再分,因为不可再分,所以在执行的时候也要么成功,要么失败,不存在一半成功一半失败的情况。
隔离性:
是指各个事物的执行都是独立、而且对同一数据的操作是互斥的。这主要是针对并发的,可能存在多个原子操作同时操作对应的数据,从而破坏数据的一致性,比如我们常说的读脏数据、重读、幻读的情况。
一致性:
想到当初学习时候,看的文章是A\B两人转钱,但总额不变的例子,这是一致性的一个例子,但是个人更认为这个一致性也是针对并发性的,设置隔离性也是为了保证一致性,所以一致性更应该体现在数据库内部数据和显示的一致性。
持久性:
就是通过原操作成功的事务,都会存库,会持久保存数据。
二、 mysql事务操作
先看一段代码,看看mysql事务的特性。首先个人创建了一个新的数据库和表:
mysql> select * from transaction;
Empty set (0.01 sec)
好,在不使用事务的情况下,我们插入2条数据:
mysql> select * from transaction;
Empty set (0.01 sec)
mysql> insert into transaction (name) values("HCC");
^[[5~Query OK, 1 row affected (0.46 sec)
mysql> insert into transaction (name) values("Marry");
Query OK, 1 row affected (0.21 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
+----+-------+
2 rows in set (0.00 sec)
不使用事务的时候,我们插入数据就直接成功了,接下来我们用事务试试:
mysql> insert into transaction (name) values("SMK");
Query OK, 1 row affected (0.00 sec)
mysql> insert into transaction (name) values("ZZD");
Query OK, 1 row affected (0.00 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 3 | SMK |
| 4 | ZZD |
+----+-------+
4 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.13 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
+----+-------+
2 rows in set (0.00 sec)
先讲述下上述的操作,首先我们开启了事务,然后插入2条数据,然后到数据库中查询数据的时候看到数据库多了2条数据,然后再事务没提交的情况下,执行rollback,再去查询发现我们插入的数据不见了。。
原因就是:我们开启事务后(begin),mysql将接下来的操作当成一个事务处理,也就是下面全部的操作是一个原子操作,再不提交的前提下,这个事务就没完成,执行rollback相当于实行失败,而回滚,所以你在查的时候发现数据库中并没用这两条数据。。。
有一个疑问,当开启事务后添加的数据真的添加到数据库中了吗,看代码
---------第一个终端----
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into transaction (name) values("SMK");
Query OK, 1 row affected (0.00 sec)
mysql> insert into transaction (name) values("ZZD");
Query OK, 1 row affected (0.00 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
+----+-------+
4 rows in set (0.00 sec)
-------开启第二个终端链接--------
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
+----+-------+
2 rows in set (0.00 sec)
通过上述代码,我们发现在另一个链接中,我们事务插入的数据并没有得到,所以感觉并不像将数据插入到数据库了,但有趣的是id直接变成5,6了,具体查没插入数据库中,我们提交事务看看第二个终端的id就可以了。。。。或者在第二个终端插入数据看id。。。。
----------第二个终端插入数据------------
mysql> insert into transaction (name) values ("zwt")
-> ;
Query OK, 1 row affected (0.17 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 7 | zwt |
+----+-------+
3 rows in set (0.00 sec)
-------------第一个终端查看---------------------
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
+----+-------+
4 rows in set (0.00 sec)
哈哈哈,会发现 第二个终端中没5,6, 第一个终端没有没有7,什么鬼??????
总结:
第二终端不显示id为5和6的条目原因:是这样的,事务在没提交的时候,对数据库进行了操作,但是没提交相当于这个原子性的事务还没执行完,而且数据库事务的隔离性采用的是repeatable,所以在第二个终端中,并没有显示,但是事务操作的已经“占位”了
第一终端不显示id 为7的条目,是因为事务没执行完,还处在事物的当中啊,哇哈哈哈。。。。是不是这样。。。0.0
提交事务,结果如下:
--------第一终端----------
mysql> commit;
Query OK, 0 rows affected (0.20 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
| 7 | zwt |
+----+-------+
5 rows in set (0.00 sec)
---------第二终端-----------
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
| 7 | zwt |
+----+-------+
5 rows in set (0.00 sec)
三 mysql中的事务操作
参考菜鸟:
-
BEGIN 或 START TRANSACTION:显式地开启一个事务;
-
COMMIT 或 COMMIT WORK:COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的;
-
ROLLBACK 或 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
-
SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;
-
RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
-
ROLLBACK TO identifier;把事务回滚到标记点;
-
SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。
前边其实使用的就是begin、commit和rollback,下面试试 savepoint、 release savepoint、 rollback to identifier以及 SET TRANSACTION。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into transaction (name) values ("MR");
Query OK, 1 row affected (0.00 sec)
mysql> insert into transaction (name) values ("ZL");
Query OK, 1 row affected (0.00 sec)
#############加入MR、ZL后,加入一个保存点,然后接着插入ZH,并查询数据############
mysql> savepoint pont1;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into transaction (name) values ("ZH");
Query OK, 1 row affected (0.01 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
| 7 | zwt |
| 8 | MR |
| 9 | ZL |
| 10 | ZH |
+----+-------+
8 rows in set (0.00 sec)
########回滚到保存点,查看数据######
mysql> rollback to pont1
-> ;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
| 7 | zwt |
| 8 | MR |
| 9 | ZL |
+----+-------+
7 rows in set (0.00 sec)
##########提交事务,查看数据##########
mysql> commit;
Query OK, 0 rows affected (0.14 sec)
mysql> select * from transaction;
+----+-------+
| id | name |
+----+-------+
| 1 | HCC |
| 2 | Marry |
| 5 | SMK |
| 6 | ZZD |
| 7 | zwt |
| 8 | MR |
| 9 | ZL |
+----+-------+
7 rows in set (0.00 sec)
这就相当于加了一个断点吗,在保证这一节点之前数据正确后,可以将数据回到这个保存点,即使后边数据损坏了,在提交事务时这部分数据也能保存。release savepoint 就不说了,就是在事务中将相应的保存点去掉。。
在试试SET TRANSACTION。。。。。。首先隔离级别如下:
隔离解别 | 脏读 | 不可重复读 | 幻读 |
Read Uncommitted | Y | Y | Y |
Read Committed | N | Y | Y |
Repeatable(default) | N | N | Y |
Serializable | N | N |
看了一篇文章很好,自己就不写了。。。。。链接在此。。。
https://www.cnblogs.com/huanongying/p/7021555.html