一.事务
事务的4个特性:
1.原子性:即一个事务不可再分割,在一个事务中的DML语句要么全成功,要么全失败。
2.一致性:即事务前后数据库中的状态应该一致,比如A给B转账,那么转账之后他们的总金额应该是不变的。
3.隔离线:即事务A不会 影响事务B
4.持久性:即事务一旦提交,那么对数据影响是永久的,就算服务器关闭,那么数据也会存在。
事务的并发问题
1.脏读:即事务B在更新数据的时候,事务A进来读走了已经更新了的数据,但是事务B还未提交,此时事务B觉得不合适,回滚了数据,那么此时事务A读取的就是脏数据。
2.不可重复读:即事务A读取数据,此时事务B进来把数据进行修改,并提交,事务A为了验证结果再次读取发现值与上次不一样。
3.可重复读:即事务A在读取事务时,会开启一个事务,禁止对我正在查询的数据进行修改等操作。
4.幻读:即事务A在查询数据的时候,发现id=1此条数据不存在,于是准备插入进来,而此时事务B进来新增加了一条id=1的数据,事务A就幻读了。
幻读与不可重复读很相像,但又不一样,不可重复读针对的是数据的更新,而幻读针对的是数据的插入。针对这两种情况,对幻读采取表锁,对不可重复读只需锁住满足条件的行。
针对上面的并发问题,我们需要用到事务隔离级别相关知识。
事务隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交(read-uncommitted) | 是 | 是 | 是 |
读已提交(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
1.针对上面的脏读,我们可以采取 read-committed 读已提交,意思说我们只能读取已经提交了值。但是不能避免不可重复读。
2.如果需要避免不可重复读,我们可以采取repeatable-read课重复读,意思说事务A在读取数据的时候,会开启一个事务,禁止其他事务对其修改。这样就避免了不可重复读,但是也不能避免幻读。这也是mysql采取的默认隔离级别,不同数据库会不一样。Sql Server 和Oracle采取的是读已提交。
3.如果避免幻读我们可以采取Serializable 序列化,Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。
随着隔离级别的提高,性能也会对应的下降。
二.mysql 的存储引擎,Inndb和Myisam
(1)InnoDB支持事务,MyISAM不支持事务,当涉及到安全性的操作时,首选InnoDB
(2)MyISAM适合查询插入为主的操作,并且执行大量查询的操作时,性能比较高,InnoDB适合频繁修改以及设计到安全性较高的操作;
(3)InnoDB支持外键和行锁(并采用间隙锁防止幻读, 某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'--在where条件没有使用主键时,照样会锁全表),MySIAM不支持外键,支持表锁(读取时对所有表加共享锁,写入时对所有表加排它锁);
(4)清空整个表时,InnoDB是一行一行的删除,效率非常慢,MyISAM则会重建表;
三.索引相关知识
索引好比字典的目录,这样大大增加了查询速度。但同时也要合理的学会使用索引,使用不当,不仅不会提高查询速度,还会影响插入,删除等效率,因为在使用索引的时候,数据库会维护一个索引表,插入和删除不仅要对原表进行修改,还要对索引表进行一个修改。mysql索引的数据结构就是用到的B+树
索引方式
聚集索引:指索引项的排序方式和表中数据记录排序方式一致的索引,每张表只能有一个聚集索引。
解释:什么叫索引项的排序方式和表中数据记录排序方式一致呢? 我们把一本字典看做是数据库的表,那么字典的拼音目录就是聚集索引,它按照A-Z排列。实际存储的字也是按A-Z排列的。这就是索引项的排序方式和表中数据记录排序方式一致。
非聚集索引:非聚集索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引
索引的分类
- 普通索引:这是最基本的索引,它没有任何限制。
- 唯一索引:与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。比如说一个组合索引 age=1,name=张三,那么表中就不允许有另外一条记录值与其相等。
- 主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。
- 组合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。比如还是如上列子,索引顺序为 age,name 。如果查询条件为 where = name那么不会使用索引。查询条件为 where age=? and name =?或者 where name =? and age=?或者 where age=? 都会使用索引,这就是遵循最左前缀。
- 全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的where语句的参数匹配。fulltext索引配合match against操作使用,而不是一般的where语句加like。全文索引只能用于InnoDB或MyISAM表,只能为CHAR、VARCHAR、TEXT列创建。