事务隔离级别和锁

3级4种隔离级别

  • 数据库操作中为了有效保证并发读取数据的正确性,定义事务隔离级别。可用多版本或者锁实现。
  • mysql默认 REPEATABLE_READ , Oracle默认 READ_COMMITTED

无隔离

  • 一个事务可以操作另一个未提交事务的数据,
  • 问题:
    • 脏读:事务A读取事务B未提交的数据。
      • 事务B更新多个对象,事务A读到其中部分对象。
      • 事务B回滚,事务A读到事务B即将回滚的数据。
    • 脏写:事务A覆盖事务B未提交的数据。
      • 不同事务的并发混在一起。
  • 使用场景:
    • 只需要保证数据可回滚或者可持久化。如只有insert,无update场景。

弱隔离

读提交
  • 事务A在事务B提交后才能读取事务B修改的数据。
  • 解决问题:
    • 脏写。行级锁,事务修改完成提交之后释放。
    • 脏读。行级锁、数据多版本。
  • 问题:
    • 不可重复读。读倾斜。
      • 由于其他事务修改单对象,导致查询该对象的状态不一致。如其他事务update、delete同一条数据。
        200412.readskew.png
可重复读
  • 事务A相同条件两次读取的数据相同。
  • 解决问题:

在innodb可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入或者修改的数据
所以说MVCC可以解决幻读。幻读在“当前读”下才会出现。

  • 问题:
    • 更新丢失。两个事务并发select->modify->update,更新冲突,LWW产生更新丢失。
      • 由于多事务对单对象操作产生直接竞争,如update和delete操作。
    • 幻读。写倾斜,事务A select-> 事务B改变部分数据-> 事务A相同条件查询获得的结果集不一样。
      • 由于多事务对一组对象中的不同部分操作产生间接竞争,如insert或者update、delete不同数据。
        • case1:insert新对象。第二次查询多了一条数据。需要区间锁,参考
        • case2:update不同对象。需要串行事务
          200412.writeskew.png

串行化

  • 解决问题:
    • 更新丢失。
      • 使用原子写操作。如 UPDATE table SET a = a + 1
      • 悲观锁。分布式锁等。
      • 乐观锁。CAS+重试。
        • 如果CAS的Where条件运行在旧的快照上,仍然无法防止更新丢失。
      • 自动检测更新丢失。PostgreSQL的可重复读、Oracle的可串行化、SQL Server的快照级别,支持检测更新丢失并终止违规事务。
      • 多主写入,不使用LWW,合并冲突。
    • 幻读。三种串行化方案。
实际执行串行
  • 方式:
    • 单线程执行,如redis。
    • 分区串行,扩展到多实例、多CPU。
    • 存储过程。
  • 条件:
    • 事务简短,如OLTP,否则影响其他事务。
    • 涉及数据可以完全加载到内存,减少I/O瓶颈。
    • 单个分区写入吞吐低,否则I/O瓶颈。
    • 跨分区事务尽量少,如同步更新二级索引。
两阶段加锁
  • X锁和S锁。写写、读写互斥,读读并发。
    • 如果只锁对象,无法解决幻读。
    • DB访问延时不确定性大。
  • 谓词锁。锁查询条件。
  • 索引区间锁。扩大保护范围,简化谓词锁。比如mysql的next-key lock
可串行化的快照隔离
  • 乐观锁原则,事务提交时检查查询结果是否改变,判断是否需要中止事务。
    • 是否读到过期版本MVCC快照。
    • 写是否影响之前的读。读加SSI锁,类似S锁但是不阻塞写事务,提交时检查冲突。
  • 实现:PostgreSQL的SSI

读写锁

排他锁

  • 排他锁又称写锁。
    • 如果事务T对数据加上排他锁后,则其他事务不能再对数据加任何类型的锁
    • 获准排他锁的事务既能读数据,又能修改数据
  • 查询语句可以使用排他锁,对查询的数据每一行加上排他锁。
SELECT ... FOR UPDATE;

共享锁

  • 共享锁又称读锁。实现读读并发
    • 如果事务T对数据加上共享锁后,则其他事务只能对数据再加共享锁,不能加排他锁。
    • 获准共享锁的事务只能读数据,不能修改数据。
  • 查询语句可以使用排他锁,读取同一版本的数据。
SELECT ... LOCK IN SHARE MODE;

锁实现4种隔离级别

  • 读未提交:任何操作都不加锁。
  • 读提交:数据的修改删除加排他锁
  • 重复读:数据读取之后加共享锁,无法锁住Insert,会幻读。
  • 串行:不能通过行锁解决,需事务串行。
  • 参考

并发控制一般使用锁和数据多版本。

提高并发的思路:

  • 普通锁:串行执行。
  • 读写锁:读读并发。
  • 数据多版本:读写并发。

参考

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值