MySQL逻辑架构
- 第一层:连接/线程管理,授权认证、安全等;
- 第二层:核心服务功能,查询、优化、解析、缓存以及所有内置函数,存储过程、触发器、视图;
- 第三层:存储引擎,负责MySQL中数据的提取和存储;事务、行级锁在该层实现。
并发控制
读写锁
读锁:共享锁,同一时刻多个客户可以同时读取同一资源互不干扰;
写锁:排他锁,一个写锁会阻塞其他写锁和读锁。
锁粒度
锁定资源粒度越小,并发度越高,锁开销越大。
表锁
尽管存储引擎可以管理自己的锁,但是MySQL本身还是会使用各种有效的表锁来实现不同的目的,比如,服务器会为 ALTER TABLE语句使用表锁而忽略存储引擎的锁机制。
行锁
行级锁只在存储引擎层实现,而MySQL服务器层没有实现。
事务
ACID
- 原子性:一个事务中的操作要么全部执行,要么全部失败回滚;
- 一致性:数据库总是从一个一致性状态到另一个一致性状态;
- 隔离性:一个事务的修改在提交前,对其他事务不可见;
- 持久性:事务一旦提交,所做的修改持久化到数据库。
隔离级别
- 未提交读:事务中的修改,即使未提交,其他事务也是可见的;
- 提交读:一个事务从开始直到提交之前,所作的修改对其他事务不可见;
- 可重复读:保证同一事务多次读取同一记录结果一致;
- 串行化:强制事务串行执行;在读取的每一行数据都加锁,会导致大量的超时和锁争用问题。
死锁
两个或多个事务在同一资源上相互争用,并请求对方已经锁定的资源,从而导致的恶性循环现象。
解决姿势:
- 查询时间到达锁等待设定的时间后,放弃锁请求;
- InnoDB处理方式:将持有最少行级排他锁的事务回滚。
事务日志
预写式日志:修改数据时只需要修改内存拷贝中的数据,并且将修改行为追加记录到持久在硬盘的事务日志中;因此修改需要两次写磁盘,一次修改行为写入日志,一次是内存中被修改的数据慢慢刷回磁盘;如果数据的修改行为已经记录到日志中而数据本身还未写回磁盘,此时系统崩溃,数据的修改也不会丢失,存储引擎重启时执行事务日志即可恢复。
多版本并发控制(MVCC)
事务型存储引擎,采用多版本并发控制减少加锁操作,降低锁开销。
InnoDB多版本并发控制的简单实现
- SELECT:1.查找版本号小于或等于当前事务版本的数据行,这样可以确保读取的数据行要么是事务开始前已存在的或者当前事务插入的行; 2.删除标识版本号要么未定义,要么大于当前事务版本号;
- INSERT:为插入的数据行保存当前系统版本号为行版本号;
- DELETE:为删除的数据行保存当前系统版本号为删除标识;
- UPDATE:先INSERT后DELETE。
MySQL存储引擎
数据表的定义由服务器层实现;
InnoDB
- 数据存储在表空间
- MVCC支持高并发,默认隔离级别可重复读,并使用间隙锁解决幻读问题;
- 聚簇索引
- 优化:可预测性预读、自适应哈希索引、插入缓冲区
- 在线热备份
MyISAM
- 全文索引、压缩