zoukankan      html  css  js  c++  java
  • MySQL 并发控制(锁得使用)

    导读

    并发问题:同一时刻进行读写,并发问题回引发数据不一致问题。

    解决并发问题:MySQL采用了锁定机制去解决并发问题

    锁的分类

      MySQL使用两种锁机制去解决问题:共享锁排他锁,也叫读锁或者写锁。

      • 共享锁、读锁:不影响其他连接的读,写会受影响
      • 排他锁、写锁:会不让其他连接进行读写

      MySQL针对不同的数据粒度,又分别使用表锁行锁进行锁定。

    锁的实现

      MySQL是使用MVCC(Multi-Version Concurrency Control)实现的(性能很好,其实并没有真正上锁)。

      • 悲观锁(真正上锁)
      • 乐观锁(通过一些递增的字段来控制逻辑上锁)

      MVCC这种机制是通过对一行数据的几个隐藏列进行操作实现的。

      B+树的数据行,其实每一行都要加上几个隐藏列(版本号,一条记录可能对应几个版本号,差不多可以这样理解,一个版本号,对应一个快照)

    服务层和存储引擎层

      服务层只是实现了表锁:

        加锁:lock table 表名 read(write),表名2 read(write)

        解锁:unlock tables;

      存储引擎层实现行锁(只有InnoDB和extraDB实现了行锁)

      存储引擎层和服务器层可能都实现了行锁,但是实现逻辑不一样,优先使用存储引擎层的实现。

      事务部分会隐式的去加行锁和表锁,其中这个表锁不是服务器层实现的表锁。

    行锁和表锁对比

      表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低

      行级锁:开销大,加锁慢;回出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最大

    MVCC并发控制,读操作分类

      在MVCC并发控制中,读操作可以分成两类:快照读(snapshot read)与当前读(current read)

      快照读,读取的记录的可见版本(有可能是历史版本),不用加锁。

      当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

    快照读:简单的select操作,属于快照读,不加锁。

    select * from table_name where ?;

    当前读:特殊的操作,插入/更新/删除操作,属于当前读,需要加锁。

    select * from table_name where ? lock in share mode;
    select * from table_name where ? for update;
    insert into table_name values (...);
    update table_name set ? where ?;
    delete from table_name where ?;

      以上都属于当前读,读取记录的最新版本。并且读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁(共享锁)外,其他的操作,都加的事X锁(排他锁)。

    InnoDB和MyISAM最大区别

    InnoDB有行级锁和事务

  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/chenyanbin/p/13126960.html
Copyright © 2011-2022 走看看