Myisam引擎和InnoDB引擎
- mysql优先选择使用innodb引擎,原因:支持事务,支持行级锁,支持外键,高效处理并发以及并发带来的一致性问题;
- Myisam的优势: 查询效率要高一些
两者的区别类似于AMD和Intel的区别;
mysql执行sql过程
客户端连接mysqld => 登录鉴权 => 【开启缓存 查看是否命中查询缓存,直接返回】 => sql语句解析成sql解析树 => 查询语句预处理器,检查解析树是否合法 => 查询优化器优化执行计划(是否命中索引,如何查询成本最小,性能最优) => 查询执行引擎(innodb)返回数据
mysql事务
事务特点(ACID)
- 原子性(Atomicity): 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。mysql默认的事务隔离级别为repeatable-read。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
事务并发问题
- 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
- 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。 => 解决办法:锁行
- 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。 => 解决办法:锁表
事务隔离级别
- 读未提交(Read uncommitted): 【事务a能读到事务b未提交的修改】
- 读提交(read committed): 写数据只会锁住相应的行,【事务a只能读到事务b提交后(commit)的修改】
- 可重复读(repeatable read): 如果检索条件有索引(包括主键索引)的时候,默认加锁方式是next-key 锁;如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读。【事务a在事务b执行过程中插入了一条新纪录】。
- 串行化(Serializable): 读写数据都会锁住整张表。
注: 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
MySQL事务隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
读提交(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
Mysql锁机制
概念
- 表锁: 表锁锁住的是一整张表,表锁是开销最小的锁策略。
- 行锁: 行锁锁住的是表中的一行数据,行锁是开销最大的锁策略【需要找到对应的行】,开销大,加锁慢,会产生死锁,发生锁冲突的概率最低,并发度也最高。【一般情况下尽量优先加行锁,为了提高并发】
- 共享读锁(S锁): 由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享读锁,不能获取排它写锁,也就是说只能读不能写。
- 排他写锁(X锁): 由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁 如果事务T对数据A加上排他写锁后,则其他事务不能再对A加任何类型的封锁,不允许进行读写。获准排他写锁的事务既能读数据,又能修改数据, 粒度大,开销小,加锁快,不会出现死锁,发出锁冲突的概率最高,并发度最低。
- 死锁: 多个进程互相等待对方锁的释放。 => 重启对应的服务;
- 锁冲突:一个进程等待另一个进程释放需要的锁;
- 悲观锁: 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
- 乐观锁: 假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。