这里写目录标题
mysql的事务
我们在说mysql数据的隔离性之前,就先要了解mysql的事务。
举个简单的例子:A用户给B用户转账,A的资金减少,B的资金增加,才算一个完整的转账。如果A的资金减少,B的资金没有增加,这就是异常的转账,A的资金需要回滚,因而,此时便需要事务来控制。
用简单的话来说,就是完成对数据表完成一系列增删减的单元操作。
在事务的范围之内,要么每条指令都执行,要么全都不执行。或许,这句话并不严谨,但这是个人的理解。
mysql事务的四大特征(ACID)
原子性(Atomicity)
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。
事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性(Consistency)
事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。
如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。
如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
隔离性(Isolation)
指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。
事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
持久性(Durability)
指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。
即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
隔离性
我们把隔离性单独拿出来讲解,讲解数据库的隔离性,就必须提到其脏读、不可重复读、幻读的概念。
脏读(Dirty Reads)
脏读的释义
所谓脏读就是对脏数据(Drity Data)的读取,而脏数据所指的就是未提交的数据。
也就是说,一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。
代码解读
-- 这是没进行事务操作的查询,按uid升序排列
mysql> select * from user1 order by uid asc;
+-----+-------+
| uid | uname |
+-----+-------+
| 1 | jack |
| 2 | rose |
| 3 | alice |
| 4 | alan |
| 5 | jan |
+-----+-------+
-- 现在开启一个事务
mysql> start transaction;
-- 向该表中插入三个数据
mysql> insert into user1(uname) values('张三'),('李四'),('王二');
-- 但是并没有提交数据
-- 我们在没有提交数据情况下去查询,于是得到下面的结果:
mysql> select * from user1;
+-----+--------+
| uid | uname |
+-----+--------+
| 4 | alan |
| 3 | alice |
| 1 | jack |
| 5 | jan |
| 2 | rose |
| 6 | 张三 |
| 7 | 李四 |
| 8 | 王二 |
+-----+--------+
我们在没有提交数据时,咋一看数据确实是插入到表中了,但事实上数据并没有插入到表中,您如果不相信的话,我们关闭这个事务后再重新打开,您会发现压根就没有这三条数据,代码如下:
mysql> select * from user1 order by uid asc;
+-----+-------+
| uid | uname |
+-----+-------+
| 1 | jack |
| 2 | rose |
| 3 | alice |
| 4 | alan |
| 5 | jan |
+-----+-------+
5 rows in set (0.00 sec)
因此,我们在没有提交事务的情况下,读到了脏数据,因而,此时的数据时不可见的,所以,我们在创建事务时,就需要用到隔离性的四个等级来限制。
不可重复读(Phantom Reads)
幻读的释义
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。
幻读的代码
-- 我们第一次user1表中的数据如下:
mysql> select * from user1 order by uid asc;
+-----+-------+
| uid | uname |
+-----+-------+
| 1 | jack |
| 2 | rose |
| 3 | alice |
| 4 | alan |
| 5 | jan |
+-----+-------+
-- 我们开启一个事务
mysql> start transaction;
-- 更新这user1表
mysql> update user1 set uid=10,uname='张三' where uid=5;
-- 提交事务
mysql> commit;
-- 再一次查询数据
mysql> select * from user1 order by uid asc;
+-----+--------+
| uid | uname |
+-----+--------+
| 1 | jack |
| 2 | rose |
| 3 | alice |
| 4 | alan |
| 10 | 张三 |
+-----+--------+
5 rows in set (0.00 sec)
当我们在读完数据时,此时,开启一个更新user1表的事务,并提交,于是,我们再次读数据时,发现这两次读到的不一样。于是,我们出现了幻读的现象。
不可重复读(Non-Repeatable Reads)
不可重复读的释义
一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。也就是说,这个事务在两次读取之间该数据被其它事务所修改。
不可重复读的代码:
-- 我们第一次读取uid等于5的数据
mysql> select * from user1 where uid=5;
+-----+-------+
| uid | uname |
+-----+-------+
| 5 | jan |
+-----+-------+
-- 此时我们开启一个事务
mysql> start transaction;
-- 更新uid为5的数据
mysql> update user1 set uid=10,uname='张三' where uid=5;
-- 提交数据
mysql> commit;
-- 我们以相同的条件,查询这一行,结果是没有数据
mysql> select * from user1 where uid=5;
Empty set (0.00 sec)
脏读是开启事务读取到了未提交数据的事务,不可重复读和幻读都是读取到已提交数据的事务,但不同的是,不可重复是正度某一行或某一个值,而幻读针对的是一系列的数据。
隔离性等级
为了避免以上出现的问题——脏读、不可重复读、幻读,我们需要对数据库进行设置隔离性的等级,它有以下四个等级。
oracle默认的是read-committed
mysql 默认repeatbale-read
如果我们在命令行中如何操作隔离性的优先级,我们可以这样做:
-- 查询当前表数据库的隔离性的优先级
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
-- 设置隔离性的优先级
mysql> set tx_isolation='serializable';
Query OK, 0 rows affected (0.00 sec)
-- 我们查看设置后的优先级
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set (0.00 sec)
总结
学习mysql事务的隔离性,在工作中是非常重要的。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99290.html