Mysql基础

Posted by YaPi on April 14, 2018

存储引擎 MyISAM和InnoDB区别

  1. MyISAM不支持外键和事务,innodb支持
  2. MyISAM锁的粒度是表级,而InnoDB支持行级锁定
  3. MyISAM支持全文类型索引,而InnoDB不支持全文索引
  4. MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM
  5. Myisam创建表生成三个文件:.frm数据表结构 .myd数据文件 .myi索引文件,Innodb只生成一个frm文件,数据存放在ibdata1.log
  6. MyisAM使用delete语句删除后并不会立刻清理磁盘空间,需要定时清理,命令:OPTIMIZE table dept;
应用场景
  • MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
  • InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。
  • 叶节点包含了完整的数据记录。这种索引叫做聚集索引,因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形
  • 第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。

索引种类

  1. 主键索引(把某列设为主键,则该列就是索引,主键不能重复) 2.唯一索引(unique),该列具有唯一性,同时又是索引
  2. index 普通索引
  3. 全文索引 (fulltext) 只有MyISAM存储引擎支持 (注:mysql 5.6之后,Innodb也开始支持全文索引,mysql5.6较之前版本有较大更新,有兴趣的小伙伴可以去查一查)

索引失效情况

  1. 最左前缀匹配:模糊查询时,使用%匹配时:’a%‘会使用索引,’%a‘不会使用索引
  2. 条件中有or,索引不会生效
  3. a and c,a生效,c不生效
  4. b and c,都不生效
  5. a and b > 5 and c,a和b生效,c不生效。

数据库锁机制

数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁)

  • 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁,其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
  • 解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。
隔离级别 脏读 不可重复读 幻读 加锁方式
未提交读(Read uncommitted) 可能 可能 可能 都不加锁,基本没用
已提交读(Read committed) 不可能 可能 可能 读不加锁,写加锁
可重复读(Repeatable read) 不可能 不可能 可能 行级别加锁
可串行化(Serializable ) 不可能 不可能 不可能 读用读锁,写用写锁 表级别加锁
  1. 脏读(Dirty reads):一个事务A读取到了另一个事务B还没有提交的数据,并在此基础上进行操作。如果B事务rollback,那么A事务所读取到的数据就是不正确的,会带来问题。
  2. 不可重复读(Non-repeatable reads):在同一事务范围内读取两次相同的数据,所返回的结果不同。比如事务B第一次读数据后,事务A更新数据并commit,那么事务B第二次读取的数据就与第一次是不一样的。
  3. 幻读(Phantom reads):一个事务A读取到了另一个事务B新提交的数据。比如,事务A对一个表中所有行的数据按照某规则进行修改(整表操作),同时,事务B向表中插入了一行原始数据,那么后面事务A再对表进行操作时,会发现表中居然还有一行数据没有被修改,就像发生了幻觉,飘飘欲仙一样。 注意:不可重复读和幻读的区别是,不可重复读对应的表的操作是更改(UPDATE),而幻读对应的表的操作是插入(INSERT),两种的应对策略不一样。对于不可重复读,只需要采用行级锁防止该记录被更新即可,而对于幻读必须加个表级锁,防止在表中插入数据。有关锁的问题,

  4. 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务新增的数据
  5. 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
  6. 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
  7. 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。这个级别很简单,读加共享锁,写加排他锁,读写互斥。使用的悲观锁的理论,实现简单,数据更加安全,但是并发能力非常差。如果你的业务并发的特别少或者没有并发,同时又要求数据及时可靠的话,可以使用这种模式。Serializable这个级别,select也会加锁

乐观锁和悲观锁

  • 在悲观锁的情况下,为了保证事务的隔离性,就需要一致性锁定读。读取数据时给加锁,其它事务无法修改这些数据。修改删除数据时也要加锁,其它事务无法读取这些数据。依靠数据库的锁机制实现
  • 乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据

复制

MySQL 的复制原理:Master 上面事务提交时会将该事务的 binlog event 写入binlog file,然后 master 将 binlog event 传到 slave 上面,slave 应用该 binlog event 实现逻辑复制。