为什么需要事务?
我们还是从最经典的例子中讲解吧:转账
需求:jeff 给jack 转账1000元
假设转账分为两部完成
1. jeff减少1000 update test set money = money -500 where name= ‘jeff’
2. jack增加1000 update test set money = money +500 where name= ‘jack’
如果在完成了第1步的时候突然宕机了,jeff的钱减少了而jack的钱没有增加那jeff岂不是白白丢了1000元;这时候就需要用到我们的事务了
事务流程:
1. START TRANSACTION开启事务(开启事务后会把所有的操作先存放到事务日志data目录下的ib_logfile0 ,ib_logfile01)
2. 进行实务操作
3. 关闭事务
a. COMMIT提交事务:同步数据保存到数据库表
b. ROLLBACK回滚事务:清空日志表
在开始之前假设jeff 和jack 账户里都有1000
START TRANSACTION开启事务
转账操作扣掉jeff 500
扣除成功,突然宕机了 (你可以尝试模拟宕机的情况1.把电脑关了2.退出mysql客户端);
我选择了退出客户端 mysql>exit;
刚才只完成了扣除jeff的500元并没有执行到给jack加500就中断了,会不会像没有开启事务一样白白损失500呢?
打开mysql客户端验证 查询账户,发现并没有扣掉500。
事实证明jeff 并没有损失500 账户里面还是原来的1000,因为你已经开启了事务宕机时已经回滚了所以不会出现白白损失500的情况
事务的特性:
1. 原子性:整个事务要么全部成功提交要么全部失败回滚,就像上面的例子扣除jeff 500时突然宕机失败了全部操作撤销。
2. 隔离性:一个事务在完成前对其他事务是不可见的请看下面图文解释
减少了jeff的1000
现在在事务没完成时在新的控制台打开mysql,查询刚才jeff账户,结果发现jeff的1000元并没有被扣除
当你COMMIT提交后在新的控制台打开mysql客户端就可以看见了
3. 一致性:事务操作前后,数据表中的数据不会发生变化(只会在日志表中发生变化这就是上面为什么事务没有提交前当前mysql客户端可以看到数据变化而同时在另外一个mysql端上看不到数据变化),直至成功提交前。在前面转账的例子中就算刚执行完扣除jeff的500后就突然宕机也不会出现损失500的情况
4. 持久性:一旦事务提交则会永久保存在数据库中
这时你可能会有疑问,为什么不开启事务时会直接提交到数据表呢?因为mysql默认采用了自动提交模式
自动提交模式(AUTOCOMMIT)
自动提交模式:如果不是显式开启一个事务,则每一个查询都被当作事务执行提交操
mysql>SHOW VARIABLES LIKE ‘AUTOCOMMIT’; 查看系统是否开启了自动提交
如果我们关闭了自动提交后(只限当前连接) mysql>SET AUTOCOMMIT = 0; 之后的所有查询操作都要显式COMMIT。
以下测试
关闭了自动提交没有COMMIT
COMMIT提交后