
事务操作
正常的转账操作:

然而如果出现异常,如下图,执行到中文肯定会报错

但是此时会导致余额发生变化,如下图

所以需要使用事务,有两种方式
方式1:修改事务的提交方式
需要修改事务的提交方式

对于mysql,每一行都是一个事务,是自动提交的,可以使用select @@autocommit 查看,如果是1就是自动,需要设置成0,之后不管怎么操作数据,只有执行 commit; 才会真正修改数据,如果出现异常,可以是执行 rollback; 回滚,这样数据就不会改变了
补充:两个@代表查看系统变量信息

方式2:开启事务

不需要修改事务提交方式,而是在执行时加上一行代码即可,如下图。同样的,执行完后不会真正修改数据,只有 commit; 后才会修改,如果出现异常, rollback; 即可

四大特性ACID

并发事务问题

事务隔离级别
性能越上面越高,安全性越下面越强,✔代表可能会出现的并发事务问题

session为针对当前客户端窗口有效,global代表针对所有客户端窗口有效
read commit 解决脏读问题
注意下图右边的操作并没有commit,但是左边的客户端依然读取到了修改的数据,即脏读

因此将事务的隔离级别改成 read committed 即可解决,如下图,第一次select是初始,第二次是右边执行,第三次是右边提交,仅第三次才发生变化

repeatable read 解决不可重复读问题
同样的一个事务中,查询出来的数据不一致,就是不可重复读,即只要其中一个客户端进行提交,想要查询的客户端即使没提交,也会读到修改后的数据,如下图

左边第一次select为初始值,第二次为右边修改数据,此时采用的是read commit,因此在右边未提交时左边依旧没发生变化;第三次select则为右边执行了commit,此时左边查询到的结果已经改变,即在左边这个事务还没完成时,数据就发生了改变。
如下图,当设置为repeatable read时,右边直接一次性commit,可以看到左边多次select保持一致,只有当commit后,才能查询到修改后的数据,此时就可以完成重复读的操作

serializable 解决幻读问题
如下图,id为主键,初始并没有id为3的人员,左边先查,没有。与此同时,右边插入了一个id为3的人员并提交。此时左边再想插入id为3的人员,却提示已存在,然后通过select查询却发现id3为空,此时就出现了幻读问题

需要将事务的隔离级别设置为serializable解决
serializable为串行操作,即同一时刻只有一个事务能进行操作,只有a事务提交了,b事务才能继续
如下图,右边的客户端想要插入数据,然后由于左边的还没有提交,因此会堵塞在插入的环节

当右边的执行完所有操作(插入id4与右边客户端一致),并提交后,右边才会继续执行,同时因为左边已经插入了id4的人员,因此右边的会报错,如下图
