最近在公司项目上遇到一个问题,客户使用某个功能经常出现重复数据,后面经排查,发下这个功能因为设计到递归,而且是一个粒度比较大的事务,
操作比较耗时,mysql数据库使用了默认的隔离级别RR,因此上一个用户操作后事务没有完成,下一个用户又重复操作了,数据被重复写入了.
解决方案是后来在事务执行之前加了一个表,用来记录操作数据id,保存前进行判断是否有记录,有则直接返回,没有则保存记录执行事务后删除记录.
现在我们来重现一下这种场景
首先新建一张表
新建三个窗口连接数据库测试
1.读未提交RC
两个窗口连接上数据库,开启事务,查询t_user表
窗口2更新t_user表
此时窗口3再执行查询语句,发现读到了事务没有提交的脏数据,这种情况称之为"脏读"
把窗口二和三的mysql退出(一定要退出,否则修改隔离级别在当前会话不生效)
2.读已提交
窗口一修改隔离级别
窗口二/三连接数据库开启事务查询
窗口二更新表数据
窗口三执行查询,发现数据没有变化
窗口二提交事务,窗口三执行查询;
这时候,我们会发现窗口三读到了窗口二提交的数据,顾名思义这种场景的隔离级别就是读已提交,在这个隔离级别下,在同一个事务中执行了两次相同查询语句的到了不一样的结果,这种现象叫"不可重复读"
3.可重复读RR
这种隔离级别解决了读已提交出现的"不可重复读"的问题,所以称之为可重复读.是mysql的默认隔离级别;
开启事务 查询
窗口二更新
窗口三读不到更新记录
窗口二提交事务,窗口三查询,依旧查询不到数据
在这个隔离级别下会出现幻读的场景
窗口二/三开启事务,窗口二插入一条数据并提交
窗口三查询数据,查不到窗口二提交的数据,但是当窗口三执行update语句时会发现有update了两条数据
再次查询,查到了数据
标签:事务,窗口,隔离,查询,提交,mysql,级别 From: https://www.cnblogs.com/jiaqirumeng/p/17168495.html