【spring】spring事务的隔离级别

一、概念介绍

    1.脏读 2.不可重复读 3. 幻读 4.是并发事务产生的问题
1.1 脏读
    1.学生表有字段名name,有一条记录为张三 2.此时有两个事务A和B都开启了 3. 事务B将张三改为李四,事务A此时查到的是李四 4.事务B出错了回滚,李四回滚为张三,事务B结束 5.事务A结束,查到的结果是李四,实际值还是张三 6.一个事务读取了另一个事务尚未提交的数据,会在该事务中产生数据不一致的问题
1.2 不可重复读
    1.学生表有字段名name,有一条记录为张三 2.此时有两个事务A和B都开启了 3. 事务A此时查到的是张三 4.事务B再将张三改为李四,然后事务B提交 5.事务A再查一次,查到的结果是李四,然后事务A提交 6.在同一个事务A中,查的两次结果不一致(这个听起来仿佛也是合理的,但得保证同一个事务中同样的查询,结果需要一致)
1.3 幻读
    1.学生表有字段名name,只有一条记录为张三 2.此时有两个事务A和B都开启了 3. 事务A此时查到张三的数量为1 4.事务B再插入一条记录为张三,然后事务B提交 5.事务A再查一次,查到的张三数量为2,然后事务A提交 6.在同一个事务A中,查的两次结果不一致(这个听起来仿佛也是合理的,但得保证同一个事务中同样的查询,结果需要一致)

是不是难以理解,这和不可重复读有啥区别,再举个例子

    1.学生表有字段名name,表中没有数据 2.此时有两个事务A和B都开启了 3. 事务A此时查是否有张三,没有查到 4.事务B再插入一条记录为张三(id=1),然后事务B提交 5.事务A插入一条记录为张三(id=1)时会报主键重复,插入失败 6.事务A再去查,发现已有一条记录为张三 7.事务A查了两次,但结果不一样,仿佛出现了幻觉

是不是还是难以理解,和不可重复读的区别在于(如果还是不理解,下面还有):

    1.不可重复读针对的是一条记录(行锁) 2.幻读针对的是整张表(表锁)

二、解决方式

2.1 解决脏读
    1.学生表有字段名name,有一条记录为张三 2.此时有两个事务A和B都开启了 3.事务B将张三改为李四,事务A此时再查会阻塞 4.事务B出错了回滚,李四回滚为张三,事务B结束 5.事务A再查,查到的结果是张三 6.事务A只能读已提交的修改 7.@Transactional(isolation = Isolation.READ_COMMITTED)
2.2 解决不可重复读
    1.学生表有字段名name,有一条记录为张三 2.此时有两个事务A和B都开启了 3.事务A此时查到的是张三 4.事务B想将张三改为李四,但是事务B会被阻塞 5.事务A再查一次,查到的结果是张三,然后事务A提交 6.在同一个事务A中可重复读,查的两次结果一致 7.事务B再将张三改为李四 8.事务A在读取的时候,张三这条数据被加了行锁,事务B是无法修改的 9.@Transactional(isolation = Isolation.REPEATABLE_READ)
2.3 解决幻读
    1.学生表有字段名name,只有一条记录为张三 2.此时有两个事务A和B都开启了 3.事务A此时查到张三的数量为1 4.事务B再插入一条记录为张三,但事务B会被阻塞 5.事务A再查一次,查到的张三数量为1,然后事务A提交 6.在同一个事务A中,查的两次结果一致 7.事务B再往表中插入一条张三 8.事务A在统计张三的数量时,学生表整个表加了表锁,事务A未提交时,事务B是无法插入和修改的 9.事务A干完了,事务B才能干,并发的直接成串行化 10.@Transactional(isolation = Isolation.SERIALIZABLE) 是不是已经理解幻读和不可重复读的区别了

三、比较

3.1 并发安全
    serializable > repeatable_read > read_commited /ˈsɪˌriəˌlaɪzəbl/
3.2 运行效率
    serializable < repeatable_read < read_commited
3.3 数据库默认事务隔离级别
    1.mysql为可重复读 2.oracle为读已提交
经验分享 程序员 微信小程序 职场和发展