事务
诞生的目的就是为了把若干个独立的操作打包成一个整体
在SQL中,有的复杂的任务需要多个SQL来执行
有的时候,也同样需要打包在一起,前一个SQL是为后一个SQL提供支持.如果后一个SQL不执行,或执行出问题了,前一个SQL就是去了意义.
通俗来说,事务就是多个SQL要么全部都执行完,要么一个都不执行.
原子性:要么全都执行完,要么一个都不执行,任务不可以在被细分了。
典型例子:
事务的原子性如何保证的呢??
在执行第二条SQL之前,无法预知这次执行会失败,怎么保证这次事务没执行呢?
其实该执行还是得执行,但是在出现执行失败之后,数据库会自动执行一些”还原性“的工作,开消除前面的SQL带来的影响,如此这般操作,就好像整个事务没有执行。这个操作就是回滚(rollback)。
数据库如何知道该还原成哪个值呢?
数据库会拿小本子,将执行过的每个操作都记录下来
事务的使用
(1) 开启事务:start transaction;
(2)执行多条SQL语句
(3)回滚或提交:rollback/commit;
说明:rollback即是全部失败,commit即是全部成功。
start transaction;
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
commit;
事务的基本特性
四个基本特性
-
原子性:事务要么全都执行完,要么一个都不执行,任务不可以在被细分了。
-
一致性:事务执行之前,和执行之后,数据库中的数据都得是合理合法的。
例如:转账之后不能出现账户为负数的情况
-
持久性:事务一旦提交之后,数据就持久化存储起来了。数据就写入到硬盘中。
-
隔离性:隔离性描述的是事务并发执行的时候,产生的情况
并发编程:写出来的代码,是并发的执行(一心二用)
当并发执行多个事务,尤其是这多个事务在尝试修改/读取同一份数据,这个时候就容易出现一些问题。事务的隔离性,就是在解决上述问题。
隔离性
脏读问题:事务A在对某个数据进行修改,修改的同时,事务B去读取了这个数据,此时事务B读到的很可能是一个“脏数据”(这个数据是一个临时的结果,而不是最总的结果)
脏读举例:
我在做数学题,我做一道题,我同桌就写一个答案,等我第一遍写完之后,同桌也写完了,然后他去玩了,紧接着我在检查题目的时候,发现刚刚做的题目答案有问题,我对答案进行了修改。此时同桌的答案就是一个错误答案(脏数据).
出现脏读的问题:原因是事务和事务之间,没有任何的隔离
加上一些约束限制,就可以有效的避免脏读问题。
处理脏读:给写操作加锁
在修改的过程中,别人不能读了(加锁的状态)
修改完成过之后,别人才可以读(接触加锁)
加入写锁之后,意味着事务之间的隔离性就高了,并发性降低了
在一个事务中,包含了多次的读操作,多次读操作的结果不一致-------> 不可重复读
不可重复读出现的原因:刚刚的约定中,写的过程中不允许读,但是没有说读的过程中不允许写。
事务的隔离性又高了,并行程度更低了
幻读问题:一个事务执行过程中,多次查询到了结果集不一样(多了一条或者少了一条)
这个操作算是一种特殊的 不可重复的读取
解决幻读问题:彻底串行化执行。
隔离性最高,并发程度最低。数据最可靠,速度最慢
以上就是隔离性相关问题:
并发(快)和隔离(准)不可能兼得
可以根据实例需要来调整数据库的隔离级别,通过不同的隔离级别就可以控制事务和事务之间的隔离性,也控制了并发程度
MySQL中事务的隔离级别,提供了这么集中
- read uncommitted :允许读取未提交的数据,并发程度最高,隔离程度最低,会引入脏读+不可重复读+幻读。
- read committed :只允许读取提交之后的数据,相当于写加锁,并发程度降低了一些,隔离程度调高了一些,解决了脏读,会引入不可重复读+幻读。
- repeatable read :相当于给读和写都加锁,并发程度又降低了,隔离程度又提高了,解决了脏读,不可重复度,会引入幻读问题。
- serializable :串行化,并发程度最低(串行执行),隔离程度最高,解决了脏读,不可重复读,幻读。
可以通过修改my,ini这个配置文件,来设置当前的隔离级别。