我们这里举一个例子
小明账户有1000元,小红账户有500元.
小明向小红发起转账,转了500给小红.
具体操作:
- 小明的账户就 -500 元
- 小红的账户就 +500 元
但是由于一些其他原因(例如网络崩溃),执行了1操作之后,就崩了,那么小明账户的钱就扣了,小红账户的钱却没加.
一旦执行了1操作,第二步出错,此时的数据就出问题了.
事务就是用来解决这么一个问题的.
事务就是把上面那两步操作绑在一起,他们要么一起执行成功,要么一起执行失败.
MySQL事务的特性分成了四点(ACID):
就是 事务中的若干操作,要么全部执行,要么全部不执行.(这里的不执行,不是说这些操作不执行,而是说,从中间某个步骤开始错了,就从这个步骤开始回滚回去rollback)
例如: 上面的1操作执行成功,2操作没有执行,那么就让小明的账户+500元
在事务执行操作前后,数据库的完整性不会因为这些操作而破坏,也就是说,事务执行前后,数据始终处于一种合法的状态.
例如: 小明本来只有1000 元,想要去转1500元给小红,是不合法.
当事务执行完毕了之后,他的操作对于数据的修改会一直持续下去.
例如: 事务完成了对数据的修改,上传到了磁盘上(提交成功后),这个时候,发生故障也不会让数据库中的数据被破坏
数据库允许多个事务同时并发执行修改和读取操作.隔离性就可用防止并发执行修改和删除的时候造成数据不一致的情况.
脏读就是一个事务A在执行修改数据的操作,此时事务A还没有完成修改操作,这个时候有另外一个事务B读取了此时的内容.此时 事务B的读操作就是脏读,
因为此时此刻的事务A还没有完成修改操作,随时都可能再次修改刚刚事务B读取到的数据.
例如小明向小红转账示例.
本来小明账户余额是1000.小红账户余额是500
此时事务A执行操作 : 小明向小红转账500元
此时事务B执行操作: 读取小明账户余额.
当事务A执行了 小明账户-500的操作,还没执行小红账户+500的操作的时候,事务B读取了小明账户余额 500.
但是是事务A此时发生错误,发生了回滚(rollback),小明账户又变成了1000,可是事务B读取到的却是500.
给写操作加锁,当一个事务在执行写操作的时候,其他事务没办法执行读操作,当事务执行完写操作,释放了锁,其他事务才能读.
不可重复读就是,事务A在执行过程中,多次读取的数据不相同,就叫不可重复读.
小明想去查自己的成绩并且看看别人成绩,老师上传成绩和检查成绩.
事务A就执行: 读小明成绩 -> 看看别人成绩 -> 再次查看自己的成绩
事务B就执行: 上传成绩 -> 发现错误成绩修改成绩
当事务B执行写操作的时候,事务A想去读操作发现写操作加锁了,没办法读,只有等待写操作完成,当事务B写操作完成后,事务A第一次读操作,发现小明考了80分,第一次读后,整个事务A还没结束,事务B进行了修改操作,将小明成绩修改成了60分,此时事务A再去读的时候,发现小明只有60分,前后数据不一致,就是不可重复读.
给读操作也加锁,当事务A在读的时候,事务B没办法修改操作,只有等事务A执行完释放锁之后,事务B才能进行操作.
幻读就是,事务A在执行过程中,多次读取的结果集不一样(数据总量不一样)
虽然读操作和写操作都加锁了,但是可以新增.
小明查看暑期作业有多少,老师上传暑期作业.
事务A 小明查看暑期作业有多少 -> 小明进行其他操作 -> 小明再次查看暑期作业有多少
事务B 老师添加暑期作业.
当事务A去执行的时候,第一次读操作,发现暑期作业只有10页.然后小明进行了其他的操作,此时事务B进行添加操作,又增加了90页.
当事务B再去查看的时候,发现作业页数变成了100页.
彻底让事务之间彻底的 串行化, 就是当事务A在执行的过程中,事务B什么也不能干,只能挂机等待.
允许读取未提交的数据
注: 隔离性最低,并发性最高,存在脏读的问题
只允许读取已提交的数据,相当于对写操作加锁.
注:隔离性提高了,并发性降低了,解决了脏读,但存在不可重复读
给读也加锁了,这是MySQL默认的隔离级别
注:隔离性又提高了,并发性更低了,解决了不可重复读,但存在幻读.
严格的串行化执行
注: 隔离性最高,并发性最低,解决了幻读问题.