Mysql事务篇,让你知道事务的用法,以及可能出现的事务问题和改进 !!!
=
7.制作过程中遇到的问题,这里有可能就是你遇到的bug,让我头痛了许久,
才知道解决方案
制作不易,觉得不错请点赞收藏 !!!
目录
1.事务简介
1.1 定义:
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系
统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
1.2 运用场景:
张三给李四转账1000块钱,张三银行账户的钱减少1000,而李四银行账户的钱要增加
1000。 这一组操作就必须在一个事务的范围内,要么都成功,要么都失败。
①.正常情况: 转账这个操作, 需要分为以下这么三步来完成 , 三步完成之后, 张三减少1000, 而李四增加1000, 转账成功
②.异常情况: 转账这个操作, 也是分为以下这么三步来完成 , 在执行第三步是报错了, 这样就导致张
三减少1000块钱, 而李四的金额没变, 这样就造成了数据的不一致, 就出现问题了。
1.3 解决方案:
我们只需要在业务逻辑执行之前开启事务,执行完毕后提交事务。如果执行过程中报错,则回滚事务,把数据恢复到事务开始之前的状态。
2.事务的实现
2.1 开启事务方式一
数据库事务会默认提交,select @@autocommit = 1;指令,如果等于1就是默认提交事务
①.首先执行set @autocommit = 0;,这个指令就是设置提交方式为手动提交
②.接下来的DML语句需要你手动提交才会把数据保存到数据库(因为我们修改了Mysql自动提交方式)
③. 然后如果看到异常信息执行 rollback; 就会恢复到提交前的数据
④.一切没问题然后commit; 提交事务
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
这里不是注释,是一个异常,会导致张三的余额减少1000,李四的余额却不变
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
rollback;
commit;
2.2 开启事务方式二:
①.开启事务
start transation;
或者
begin;
②.如果在事务执行过程中出现错误,你可以回滚(Rollback)整个事务,使数据库回到事务开始之前的状态
rollback;
③.如果一切顺利,你可以提交(Commit)事务,使得对数据库的更改永久生效。
commit;
3.事务的四大特性(ACID)
原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
4.事务的并发问题
①.脏读(Dirty Read):一个事务读取了另一个事务未提交的数据。如果另一个事务在读取数据后回滚,那么第一个事务读取到的数据就是无效的。这种情况下,第一个事务读取的数据称为“脏数据”。
②.不可重复读(Non-repeatable Read):一个事务内多次读取同一数据,在事务执行期间,另一个事务对该数据进行了修改并提交。这样,两次读取的数据可能不一致,导致“不可重复读”。
③.幻读(Phantom Read):一个事务内多次查询某一范围的数据,在事务执行期间,另一个事务对该范围内的数据进行了插入或删除操作,并提交了事务。导致第一个事务的两次查询结果不一致,即出现了“幻影行”。
5.事务隔离级别
5.1 四种事务隔离级别
其中默认的隔离级别是可重复读
Serializable:每个事务都完全看不到其他事务的影响,就好像它们是按顺序一个接一个地执行的,如果有并发情况,另外的会被阻塞,只允许一个事务进行操作。
5.2 查看事务的隔离级别
mysql版本低用:
select @@tx_isolation;
mysql版本高用:
select @@transaction_isolation;
5.3 设置事务隔离级别
set [ session | global ] transaction isolation level { read uncommitted |
read committed | repeatable read | serializable }
注意:
①.事务隔离级别越高,数据越安全,但是性能越低。
②.想要演示效果的话,只需要打开两个命令行窗口,同时开启事务
6.Mysql命令行演示隔离级别
6.1 脏读
6.2 不可重复读
6.3 幻读
7.制作过程中遇到的问题
在测试的时候,我用隔离级别是可重复读,但是却测出来不可重复读问题,这让我很纳闷,
后面才知道原因是下面①所述,我在一个事务开启前查询了数据,然后再另外一个事务修改数据
并提交,事务会出现了不可重复读现象。解决方案就是开启事务之后再查询就不会了
可重复读(EPEATABLE READ)的隔离级别,也可能会出现不可重复读(Non-repeatable Read)的问题。这可能是由于以下原因导致的:
①.事务中的读取与写入操作顺序不同:
比如,在开启事务A之前先读取了某个数据,然后事务B修改了这个数据,接着事务A再次读取同样的数据,此时就会发现数据不一致,即出现了不可重复读的问题。
②.不使用行级锁或锁定范围不够
③.并发事务修改数据