一、mysql的innodb和myisam区别 1、InnoDB 支持事务MyISAM 不支持InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一。InnoDB,是MySQL的数据库引擎之一,现为MySQL的默认存储引擎,为MySQL AB发布binary的标准之一。

2、InnoDB 是聚集索引,MyISAM 是非聚集索引。

InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

3、InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。

4、InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一

详细解析MySQL中的innodb和myisam_不可重复读

详细解析MySQL中的innodb和myisam_不可重复读_02

InnoDB的逻辑存储结构如下图所示:

详细解析MySQL中的innodb和myisam_不可重复读_03

二、为什么innodb不保存表的具体行数,执行select count(*) from table时需要全表扫

1、对于MyISAM:


因为MySQL对该引擎的count有对应优化,精确的行数会被储存在存储引擎中,因此此类没有where条件的单表总行数查询会迅速返回结果。


2、对于InnoDB:


因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。




三、事物的隔离级别和解决的问题

●读未提交(Read uncommitted):允许读取尚未提交的数据变更。可能会导致脏读、幻读或不可重复读。


●读已提交(Read committed) (实现了 mvcc):允许读取已经提交的数据。可能会导致幻读和不可重复读。


●可重复读(Repeatable read)  (实现了 MVCC) (默认):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改。可能会导致幻读。


●可串行化:最高隔离级别。




1、什么是脏读?


(针对未提交数据)如果一个事务中对数据进行了更新,但事务还没有提交,另一个事务可以“看到”该事务没有提交的更新结果,这样造成的问题就是,如果第一个事务回滚,那么,第二个事务在此之前所“看到”的数据就是一笔脏数据。


 


一句话:事务A读取到了事务B已经修改但尚未提交的数据


2、什么是不可重复读?


(针对其他提交前后,读取数据本身的对比)不可重复读取是指同一个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的,所以,Read Uncommitted也无法避免不可重复读取的问题。


一句话:事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性


3、什么是幻读?


(针对其他提交前后,读取数据条数的对比) 幻读是指同样一笔查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。在Read Uncommitted隔离级别下, 不管事务2的插入操作是否提交,事务1在插入操作之前和之后执行相同的查询,取得的结果集是不同的,所以,Read Uncommitted同样无法避免幻读的问题。


事务A读取到了事务B提交的新增数据,不符合隔离性


tip:不可重复读和幻读两者有些相似。但不可重复读重点在于update和delete,而幻读的重点在于insert。