订单、库存两个表 如何保证数据的一致性?
答:在一个电子商务系统中,正常的应该是订单生成成功后,相应的库存进行减少必须要保证两者的一致性,但有时候因为某些原因,比如程序逻辑问题,并发等问题,导致下单成功而库存没有减少的情况。这种情况我们是不允许发生的,MySQL的中的事务刚好可以解决这一问题,首先得选择数据库的存储引擎为InnoDB的,事务规定了只有下订单完成了,并且相应的库存减少了才允许提交事务,否则就事务回滚,确保数据一致性。
外键的作用
答:保持数据一致性,完整性,主要目的是控制存储在外键表中的数据。
什么是读锁,什么是写锁?
读锁:也叫共享锁、死锁,若事务T对数据对象A加上读锁,则事务T可以读A但不能修改A,其他事务只能再对A加读锁,而不能加写锁,直到T释放A上的读锁。这保证了其他事务可以读A,但在T释放A上的读锁之前不能对A做任何修改。
写锁:又称排他锁、血锁。若事务T对数据对象A加上写锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
数据库中,什么是锁?
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
MyISAM和InnoDB存储引擎使用的锁:
- MyISAM采用表级锁(table-level locking)。
- InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
表级锁和行级锁对比:
- 表级锁: Mysql中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和InnoDB引擎都支持表级锁。
- 行级锁: Mysql中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
InnoDB存储引擎的锁的算法有三种:
- Record lock:单个行记录上的锁
- Gap lock:间隙锁,锁定一个范围,不包括记录本身
- Next-key lock:record+gap 锁定一个范围,包含记录本身
mysql事务隔离级别,说下你对事务的隔离性的理解?
为了达到上述事务特性,数据库定义了几种不同的事务隔离级别:
READ_UNCOMMITTED(未授权读取): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
READ_COMMITTED(授权读取): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
REPEATABLE_READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
SERIALIZABLE(串行): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
这里需要注意的是:
Mysql 默认采用的 REPEATABLE_READ隔离级别
Oracle 默认采用的 READ_COMMITTED隔离级别.
事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVVC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。
什么是事务?及其特性?
是一系列的数据库操作,是数据库应用的基本逻辑单位。
事务特性:(ACID)
1、原子性(Atomicity):即不可分割性,事务要么全部被执行,要么就全部不被执行。
2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
请问 varchar 和 char有什么区别?
char是固定长度的字符类型,分配多少空间,就占用多长空间。
Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低
例如:char(100) 存储abc 占用的空间就是100
varchar(100) 存储 abc 占用空间是4 存储的是abc 3个字节 加上字符的长度 3 就是 3+1 =4
Mysql的存储引擎,myisam和innodb的区别
区别:
1.InnoDB支持事务,MyISAM不支持
对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
2.InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
3.InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。
但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此主键不应该过大,因为主键太大,其他索引也都会很大。
而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
4.InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
5.Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;
组合索引 (a,b,c),支持哪些基于索引的查找
最左原则
对于联合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
例如索引是key index (a,b,c). 可以支持a 、 a,b 、ac、 a,b,c 4种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。
什么情况下应不建或少建索引
1、表记录太少
2、经常插入、删除、修改的表
3、数据重复且分布平均的表字段,假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。
4、经常和主字段一块查询但主字段索引值比较多的表字段
什么是表分区?
表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。
分表:指的是通过一定规则,将一张表分解成多张不同的表。比如将用户订单记录根据时间成多个表。
分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。
MySQL支持的分区类型有哪些?
- RANGE分区: 这种模式允许将数据划分不同范围;例如可以将一个表通过年份划分成若干个分区
- LIST分区: 这种模式允许系统通过预定义的列表的值来对数据进行分割;按照List中的值分区,与
- RANGE的区别是,range分区的区间范围值是连续的。
- HASH分区 :这中模式允许通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区;例如可以建立一个对表主键进行分区的表。
- KEY分区 :上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。
关于MVCC的了解
MySQL InnoDB存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control)
注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control
MVCC最大的好处:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,现阶段几乎所有的RDBMS,都支持了MVCC。
1.LBCC:Lock-Based Concurrency Control,基于锁的并发控制
2.MVCC:Multi-Version Concurrency Control
基于多版本的并发控制协议。纯粹基于锁的并发机制并发量低,MVCC是在基于锁的并发控制上的改进,主要是在读操作上提高了并发量。
MySQL优化
1>业务优化,数据库设计
2>数据库索引
3>分表分库(水平分割,垂直分割)
4>读写分离
5>存储过程(模块化编程,可以提高速度)
6>对MySQL配置优化(配置最大并发数my.ini,调整缓存大小)
7>SQL调优
8>选择正确的存储引擎
9>定时清除不需要的数据,定时进行碎片整理
10>热点数据采用Nosql等替代品
11>模糊查询采用es等替代品
12>mysql配置优化
13>服务器优化(操作系统和硬件)
大表优化,以及谈谈你对mysql分库分表的见解
当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:
1.限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。;
2.读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读;
3.缓存: 使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存;
4.垂直分区:
根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。
简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。
垂直拆分的优点:
可以使得行数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表
的结构,易于维护。
垂直拆分的缺点:
主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此
外,垂直分区会让事务变得更加复杂;
5.水平分区:
保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。
水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。
水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MySQL 并发能力没有什么意义,所以 水平拆分最好分库 。
水平拆分能够 支持非常大的数据量存储,应用端改造也少,但 分片事务难以解决 ,跨界点Join 性能较差,逻辑复杂
innodb索引用的数据结构是?
用的是树(B+树)
【索引失效】在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?
1、没有遵循索引最左原则。
建立几个复合索引字段,最好就用上几个字段。
2、最佳左前缀法则
如果索引了多列,要遵守最左前缀法则,指的是查询从索引的最左前列开始,可以跳过但是尽量不跳过索引中间的列。
3、不再索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
4、存储引擎不能使用索引中范围条件右边的列。(范围之后全失效)
若中间索引列用到了范围(>、<、like等),则后面的索引全失效
5、Mysql在使用不等于(!=、<>)或like的左模糊的时候无法试用索引会导致全表扫描
6、IS NULL和IS NOT NULL也无法使用索引
7、字符串不加单引号索引失效,因为这里有一个隐式的类型转换操作,更严重会导致行锁变表锁,降低SQL效率
以上情况,MySQL无法使用索引.
mysql的水平拆分和垂直拆分
1,水平分割:
例:QQ的登录表。假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从这100亿中查找,会很慢很慢。如果将这一张表分成100份,每张表有1亿条,就小了很多,比如qq0,qq1,qq1…qq99表。
用户登录的时候,可以将用户的id%100,那么会得到0-99的数,查询表的时候,将表名qq跟取模的数连接起来,就构建了表名。比如123456789用户,取模的89,那么就到qq89表查询,查询的时间将会大大缩短。
这就是水平分割。
2,垂直分割:
垂直分割指的是:表的记录并不多,但是字段却很长,表占用空间很大,检索表的时候需要执行大量的IO,严重降低了性能。这时需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。
例如学生答题表tt:有如下字段:
Id name 分数 题目 回答
其中题目和回答是比较大的字段,id name 分数比较小。
如果我们只想查询id为8的学生的分数:select 分数 from tt where id = 8;虽然知识查询分数,但是题目和回答这两个大字段也是要被扫描的,很消耗性能。但是我们只关心分数,并不想查询题目和回答。这就可以使用垂直分割。我们可以把题目单独放到一张表中,通过id与tt表建立一对一的关系,同样将回答单独放到一张表中。这样我们插叙tt中的分数的时候就不会扫描题目和回答了。
你用什么软件实现数据库高可用?
MHA
mysql执行一条sql语句的完整过程,sql语句在mysql中的执行过程
MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。
SQL 等执行过程分为两类,一类对于查询等过程如下:
权限校验—》查询缓存—》分析器—》优化器—》权限校验—》执行器—》引擎
对于更新等语句执行流程如下:
分析器----》权限校验----》执行器—》引擎—redo log prepare—》binlog—》redo log commit
说说mysql主从同步怎么做的?
master提交完事务后,写入binlog
slave连接到master,获取binlog
master创建dump线程,推送binglog到slave
slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中
slave再开启一个sql线程读取relay log事件并在slave执行,完成同步
slave记录自己的binglog
主键、外键和索引的区别?
主键、外键和索引的区别
定义:
主键–唯一标识一条记录,不能有重复的,不允许为空
外键–表的外键是另一表的主键, 外键可以有重复的, 可以是空值
索引–该字段没有重复值,但可以有一个空值
作用:
主键–用来保证数据完整性
外键–用来和其他表建立联系用的
索引–是提高查询排序的速度
个数:
主键–主键只能有一个
外键–一个表可以有多个外键
索引–一个表可以有多个唯一索引
什么是存储过程?用什么来调用?
答:存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个命令对象来调用存储过程。