一、事务隔离级别,每个隔离级别会引发什么问题?MySql默认的隔离级别是哪一个?有什么特征?
事务的并发问题:
- 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读到的是脏数据
- 不可重复读:事务A多次读取同一数据,事务B在事务A多次读取数据的时候,对数据做了更新并提交,导致事务A多次读取的数据不一致
- 幻读:幻读解决了不可重复读,保证了同一事务里面,查询的结果都是事务开始时的状态(一致性)
事务的隔离级别:
- 读未提交:另一个事务修改了数据,但是未提交,而本事务中的 SELECT 会读到这些未提交的数据(脏读)
- 不可重复读:事务A多次读取同一数据,事务B在事务A多次读取数据的时候,对数据做了更新并提交,导致事务A多次读取的数据不一致
- 可重复读:在同一个事务里,SELECT 的结果是事务开始时间点的状态,因此,同样的 SELECT 操作读到的结果是一致的,但是会有幻读的现象
- 串行化:事务的最高隔离级别,在这个隔离级别下不会产生任何影响。并发事务,就像事务一个一个按照顺序执行医院
事务的默认隔离级别:repeatable-read
事务的特征:原子性、一致性、隔离性、持久性
- 原子性:事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
- 一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
- 隔离性:一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性:指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
二、Mysql的储存引擎MyISAM和InnoDB的区别?为什么MyISAM会比Innodb 的查询速度快?如何选择?
区别:
MyISAM | InnoDB | |
存储结构 | 每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。 | 所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。 |
存储空间 | 可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表 | 需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。 |
可移植性、备份及恢复 | 数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。 | 免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了 |
事务支持 | 强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。 | 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。 |
AUTO_INCREMENT | 可以和其他字段一起建立联合索引。引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,可以根据前面几列进行排序后递增。 | InnoDB中必须包含只有该字段的索引。引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列。 |
表锁差异 | 只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。 | 支持事务和行级锁,是innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。 |
全文索引 | 支持 FULLTEXT类型的全文索引 | 不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。 |
表主键 | 允许没有任何索引和主键的表存在,索引都是保存行的地址。 | 如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。 |
表的具体行数 | 存有表的总行数,如果select count(*) from table;会直接取出出该值。 | 没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。 |
CURD操作 | 如果执行大量的SELECT,MyISAM是更好的选择 | 如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令。 |
外键 | 不支持 | 支持 |
为什么MyISAM会比Innodb 的查询速度快:
- INNODB在做SELECT的时候,要维护的东西比MYISAM引擎多很多;
- 数据块,INNODB要缓存,MYISAM只缓存索引块, 这中间还有换进换出的减少;
- innodb寻址要映射到块,再到行,MYISAM 记录的直接是文件的OFFSET,定位比INNODB要快
- INNODB还需要维护MVCC一致;虽然你的场景没有,但他还是需要去检查和维护
如何选择合适的引擎:
- MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
- InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。