大数据面试题之Mysql:每日三题(四)
我很喜欢的一句勉励今天的自己和大家:“人生当中成功只是一时,失败却是主旋律,但是如何面对失败,却把人分成了不同的样子,有的人会被失败击倒,有的人会爬起来继续向前。我想真正的成熟应该不是追求完美,而是直面自己的缺憾,这才是生活的本质。罗曼罗兰曾说过:“这个世界上只有一种真正的英雄主义,那就是认清生活的真相并且仍然热爱它。”
1.索引的优缺点
索引的优点
1.可以通过建立唯一索引或者主键索引,保证数据库表中每一行数据的唯一性;
2.建立索引可以大大提高检索的数据,以及减少表的检索行数;
3.在表连接的连接条件,可以加速表与表直接的相连;
4.在分组和排序字句进行数据检索,可以减少查询时间中分组和排序时所消耗时间(数据库的记录会重新排序)
5.建立索引,在查询中使用索引,可以提高性能。
索引的缺点
1.创建索引和维护索引,会耗费时间,随着数据量的增加而增加;
2.索引文件会占用物理空间,除了数据表需要占用物理空间之外,每一个索引还会占用一定的物理空间。
3.当对表的数据进行insert,update,delete的时候,索引也要动态的维护,这样就会降低的维护速度,(建立索引会占用磁盘空间的索引文件).
2.普通索引,唯一索引,主键索引,联合索引的区别
普通索引:由关键字key或者index定义的索引的唯一任务是加快对数据的访问速度,一张表允许创建多个普通索引,并且允许数据重复和NULL。主键索引(Primary key):数据表的主键列使用的就是主键索引。一张数据表有只能有一个主键,并且主键不能为null,不能重复。唯一索引(Unique Key):唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为NULL,一张表允许创建多个唯一索引。建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。也就是说,唯一索引可以保证数据记录的唯一性。联合索引:可以覆盖多个数据列,像index(columnA,columnB)索引,这就是联合索引主键和唯一索引的区别主要有以下几点:
1)主键一定会创建一个唯一索引,有唯一索引的列不一定为主键;
2)主键不允许空值,唯一索引列允许空值;
3)一个表只能有一个主键,但是可以有多个唯一索引;
4)主键可以被其它表引用为外键,唯一索引列不可以;
5)主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者存在本质的区别。
3.MySQL有哪些锁
-
事务:一组操作要么全部成功,要么全部失败,目的是为了保证数据最终的一致性
-
事务ACID特性:
- 原子性(Atomicity) :当前事务的操作要么同时成功,要么同时失败。原则性由undo log日志来保证
- 一致性(Consistency):使用事务的最终目的,由业务代码正确逻辑保证
- 隔离性(Islation):在事务并发执行时,他们内部的操作不能相互干扰
- 持久性(Durability):一旦提交了事务,它对数据库的改变就应该是永久性的。持久性由redo log日志来保证
- Mysql引入了redo log,Buffer Pool内存写完了,然后会写一份redo log,这份redo log记载着这次在某个页面上做了什么修改,即便mysql在中途挂了,我们还可以根据redo log来对数据进行恢复,redo log是顺序写的,写入速度很快。并且它记录的是物理修改(xxx页做了xxx修改),文件的体积很小,恢复速度很快。
-
事务隔离性
innoDB引擎中,定义了四种隔离级别供我们使用,级别越高事务隔离性越好,但性能越低,而隔离性是由Mysql的各种锁以及MVCC机制来实现的- read uncommit(读未提交):有脏读问题
- 脏读:事务A读取到事务B未提交的数据,数据不一致。
- read commit(读已提交):有不可重复读问题
- (并发更新) 指在同一次事务中前后查询不一致的问题
- repeatable read(可重复读):有幻读问题
- (并发插入,删除) 一次事务中前后数据量发生变化,用户产生,不可预料的问题
- serializable(串行):上面问题全部解决
- read uncommit(读未提交):有脏读问题
-
读锁(共享锁,S锁):Select…lock in share mode; //串行化
读锁是共享的,多个事务可以同时读取同一个资源,但不允许其他事务修改。 -
写锁(排它锁,x锁):select… for update;
写锁是排他的,会阻塞其他的写锁和读锁,update,delete,insert都对加写锁 -
MVCC机制
MVCC多版本并发控制,就可以做到读写不阻塞,且避免了类似脏读这样的问题,主要通过undo日志链来实现 事务id和回滚指针
read commit(读已提交),语句级快照
repeatable read (可重复读),事务级快照 -
长事务的影响
- 并发情况下,数据库连接池容易撑爆
- 锁定太多的数据,造成大量的阻塞和锁超时
- 执行时间长,容易造成主从延迟
- 回滚所需要的时间比较长
- undo log膨胀
- 容易导致死锁
-
长事务的优化
- 将查询等数据准备操作放在事务外
- 事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久
- 事务中避免一次性处理太多数据,可以拆分成多个事务分次处理
- 更新等涉及加锁的操作尽可能放在事务靠后的位置
- 能异步处理的尽量异步处理
- 应用侧(业务代码)保证数据一致性,非事务执行
-
从锁的粒度上分mysql支持锁的表级锁,行级锁(innodb),页级锁(BDB)
-
从锁的操作上说可以分为读锁和写锁
-
从实现方式上分乐观锁和悲观锁
使用的场景:
修改数据库表结构会自动加表级锁一元数据锁
更新数据未使用索引,行级锁会上升为表级锁
更新数据使用索引会使用行级锁
select。。。for update 会使用行级锁