MySQL架构基础

版权声明:转载请注明出处! https://blog.csdn.net/litianxiang_kaola/article/details/82983739

MySQL体系结构

总的来说, MySQL可以看成是二层架构, 第一层是SQL层, 在MySQL数据库系统处理底层数据之前的所有工作都是在这一层完成的, 包括权限判断SQL解析、执行计划优化、Query Cache的处理等等. 第二层是存储引擎层, 也就是底层数据存取操作的实现部分, 由多种存储引擎共同组成.

各模块工作流程

MySQL的存储引擎

MySQL使用插件式的存储引擎结构, 可以根据不同的业务场景选择不同的存储引擎. MySQL最常用的存储引擎是InnoDB和MyISAM, 两者的区别如下:

对比项 InnoDB MyISAM
外键 支持 不支持
事务 支持 不支持
行表锁 行锁, 适合高并发操作 表锁, 不合适高并发操作
缓存 缓存索引和真实数据, 对内存要求较高 只缓存索引
表空间
关注点 事务 性能
默认安装

在大数据量,高并发量的互联网业务场景下,请使用InnoDB:

  • 事务,对数据一致性帮助很大
  • 行锁,对提高并发帮助很大

事务

事务的特性

  • 原子性(atomicity)
    一个事务必须被视为一个不可分割的最小工作单元, 整个事务中的所有操作要么全部执行成功, 要么全部失败回滚, 对于一个事务来说, 不可能只执行其中的一部分操作.
  • 一致性(consistency)
    事务必须使数据库从一个一致性的状态变换到另一个一致性的状态, 也就是说一个事务执行之前和执行之后都必须处于一致性的状态. 拿转账来说, 假设用户A和用户B两者的钱加起来一共是5000, 那么不管A和B之间如何转账, 转几次账, 事务结束后两个用户的钱相加起来应该还得是5000, 这就是事务的一致性.
  • 隔离性(isolation)
    并发的事务之间是相互隔离的, 一个事务所做的修改在最终提交之前, 对其他事务是不可见的. 例如, 账户A有5000元存款, 执行完转账语句(-500), 只要该事务没有提交, 对其他事务来说账户余额还是5000元.
  • 持久性(durability)
    事务一旦提交, 其对数据库的修改就是永久性的, 即使系统崩溃, 修改的数据也不会丢失.

并发事务带来的问题

  • 更新丢失(Lost Update)
    多个事务修改同一行记录, 后面的修改覆盖了前面的修改.
  • 脏读(Dirty Reads)
    一个事务可以读取另一个事务未提交的数据.
  • 不可重复读(Non-Repeatable Reads)
    同一个事务中执行两次相同的查询, 可能得到不一样的结果. 这是因为在查询间隔内,另一个事务修改了该记录并提交了事务.
  • 幻读(Phantom Reads)
    当某个事务在读取某个范围内的记录时, 另一个事务又在该范围内插入了新的记录, 当之前的事务再次读取该范围的记录时, 会产生幻行.

隔离级别
在MySQL常用的存储引擎中, 只有InnoDB支持事务, 所以这里说的隔离级别指的是InnoDB下的事务隔离级别.

  • READ UNCOMMITTED(读未提交)
    在该隔离级别, 事务中的修改即使没有提交, 对其他事务也都是可见的. 避免了更新丢失的发生.
  • READ COMMITTED(读已提交)
    在该隔离级别, 一个事务只能看见已经提交的事务所做的修改. 避免了更新丢失和脏读.
  • REPEATABLE READ(可重复读)
    MySQL默认的隔离级别, 该级别保证了在同一个事务中多次读取同样的记录的结果是一致的. 避免了更新丢失、脏读、不可重复读和幻读. (注意看MySQL官网, RR隔离级别下解决了幻读问题)
  • SERIALIZABLE(可串行化)
    SERIALIZABLE是最高的隔离级别, 它通过强制事务串行化执行, 避免了并发事务带来的问题.
隔离级别 读数据一致性 更新丢失 脏读 不可重复读 幻读
读未提交 最低级别, 只能保证不读取物理上损坏的数据 ×
读已提交 语句级 × ×
可重复读 事务级 × × × ×
可串行化 最高级别, 事务级 × × × ×

MySQL锁机制

MySQL有三种类型的锁:

  • 表锁: 开销小, 加锁快, 不会出现死锁; 锁定粒度大, 发生锁冲突的概率最高, 并发度最低.
  • 行锁: 开销大, 加锁慢, 会出现死锁; 锁定粒度最小, 发生锁冲突的概率最低, 并发度也最高.
  • 页锁: 开销和加锁时间介于表锁和行锁之间, 会出现死锁; 锁定粒度介于表锁和行锁之间, 并发度一般.

表锁

MyISAM存储引擎使用的是表锁, 表锁有两种模式: 读锁(read lock)和写锁(write lock), 也叫共享锁(shared lock)和排他锁(exclusive lock). 读锁和写锁的关系如下:

  • 某一事务对表进行读操作(加读锁), 不会阻塞其他事务对同一表的读操作, 但会阻塞写操作. 只有当读锁释放后, 其他事务才能执行写操作.
  • 某一事务对表进行写操作(加写锁), 会阻塞其他事务对同一表的读和写操作, 只有当写锁释放后, 才会执行其他事务的读写操作.
是否兼容 读锁(共享锁) 写锁(排他锁)
读锁(共享锁)
写锁(排他锁)

MyISAM存储引擎在执行查询操作之前, 会自动给涉及的所有表加读锁, 在执行更新操作(update、delete、insert)之前, 会自动给涉及的表加写锁. 这个过程并不需要用 lock table 命令给表显示加锁.

MyISAM存储引擎在自动加锁时, 总是一次性获得 sql 语句所需要的全部锁, 所以显示锁表的时候, 必须同时给所有涉及的表加锁. 这也是 MyISAM 表不会出现死锁(deadlock)的原因.

行锁

InnoDB存储引擎使用的是行锁, 行锁的共享锁和排他锁与表锁类似, 差别在于行锁作用于某一行记录.

关于InnoDB锁的详细介绍, 看这篇文章: InnoDB并发控制

猜你喜欢

转载自blog.csdn.net/litianxiang_kaola/article/details/82983739