Mysql 一致性

关系型数据库的一致性

3种读

脏读

一个事务读取到另一个事务未提交的数据

不可重复读

不可重复读的重点是修改;同样的条件,

第1次和第2次读取id相同的记录,值却不一样。

幻读

幻读的重点在于新增或者删除;同样的条件, 第1次和第2次查出的记录数不一样

不可重复读解决

  • 对于前者, 只需要锁住满足条件的记录

    select * from user where userid=111 LOCK IN SHARE MODE; ;

  • 对于幻读, 锁住条件依然无效

    比如select * from user where enable=1 for update

    此时别的事务 新增 了一条enable=1的记录

    再次执行select ...for update时,幻读还存在

  • 快照读(普通的select 无幻读问题)

幻读解决方案

https://blog.csdn.net/nandao158/article/details/116007366

4种隔离级别

以上三种问题,将隔离级别划分为四种。

  • read uncommited 未提交读
  • 会有脏读
  • read commited 已提交读
    • 无脏读问题 (oracle默认隔离级别)
  • repeatable read 可重复读
    • 无不可重复读问题。 (mysql 默认隔离级别)
  • serializable 序列化
    • 无幻读问题 。SERIALIZABLE会在读取的每一行数据上加锁

共享锁和排它锁

MySQL数据库的锁,按照作用范围划分为: 行级锁、页级锁和表级锁

行级锁又分为共享锁和排他锁两种

共享锁、读锁

select ...lock in share mode 其他事务可读不可改。

排它锁、写锁、独占锁

select ...for update 其他事务不可读

insert /delete/update

使用场景

订单的商品数量
    如果是同一张表的应用场景,举个例子,电商系统中计算一种商品的剩余数量,在产生订单之前需要确认商品数量>=1,产生订单之后应该将商品数量减1。
    1 select amount from product where product_id=1;
    2 update product set amount=amount-1 where product_id=1 ;

如果1查询出amount为1,但是这时正好其他session也买了该商品并产生了订单,那么amount就变成了0,那么这时第二步再执行就有问题。

那么采用lock in share mode可行吗,也是不合理的,因为两个session同时锁定该行记录时,这时两个session再update时必然会产生死锁导致事务回滚。

总结

lock in share mode适用于两张表存在业务关系时的一致性要求,for update适用于操作同一张表时的一致性要求。

MVCC

(Multiversion Concurrency Control)多版本并发控制

如何解决加锁后的性能问题的?

答案就是,MVCC多版本并发控制!它实现读取数据不用加锁,可以让读取数据同时修改。修改数据时同时可读取。

覆盖索引、回表

https://zhuanlan.zhihu.com/p/339666157

posted @ 2022-06-01 10:10  赵钱富贵  阅读(158)  评论(0编辑  收藏  举报