#、count(*)、count(1)、count(列名)区别
1、count(*)、count(1):
count(*)对行的数目进行计算,包含NULL,count(1)这个用法和count(*)的结果是一样的。
如果表没有主键,那么count(1)比count(*)快。表有主键,count(*)会自动优化到主键列上。
如果表只有一个字段,count(*)最快。
count(1)跟count(主键)一样,只扫描主键。count(*)跟count(非主键)一样,扫描整个表。明显前者更快一些。
count(1)和count(*)基本没有差别,但在优化的时候尽量使用count(1)。
2、count(1)、count(列名):
(1) count(1) 会统计表中的所有的记录数,包含字段为null 的记录。
(2) count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。
语法、优化
#、一条sql,记录常用关键字顺序;
select description, count(description) num
from visit_record
group by description
order by num desc
limit 30, 15
sql执行顺序
from——join,on——where——group by——avg,sum——having——select——distinct——order by——limit
sql优化
1、在表中建立索引,优先考虑where、group by使用到的字段。
2、尽量避免使用select *。
3、尽量避免使用in 和not in,会导致数据库引擎放弃索引进行全表扫描。如下:
- SELECT * FROM t WHERE id IN (2,3)
- SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)
- 优化方式:如果是连续数值,可以用between代替。如下:
- SELECT * FROM t WHERE id BETWEEN 2 AND 3
- 如果是子查询,可以用exists代替。如下:
- SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)
4、尽量避免使用or,会导致数据库引擎放弃索引进行全表扫描。如下:
- SELECT * FROM t WHERE id = 1 OR id = 3
- 优化方式:可以用union代替or。如下:
- SELECT * FROM t WHERE id = 1 UNION SELECT * FROM t WHERE id = 3
5、尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。如下:
- SELECT * FROM t WHERE username LIKE '%li%'
- 优化方式:尽量在字段后面使用模糊查询。如下:
- SELECT * FROM t WHERE username LIKE 'li%'
6、尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描。如下:
- SELECT * FROM t WHERE score IS NULL
- 优化方式:可以给字段添加默认值0,对0值进行判断。如下:
- SELECT * FROM t WHERE score = 0
7、尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。如下:
- SELECT * FROM t2 WHERE score/10 = 9
- SELECT * FROM t2 WHERE score = 10*9
8、当数据量大时,避免使用where 1=1的条件。
#、术语解释:
脏读:事务2把事务1写完且未提交的数据读出来;
重复读:事务2读取数据后,事务1对数据进行修改,当事务2再次读取的时候发现两次读取的结果不一致(不希望这样,希望两次读取的相同)
幻读:事务2读取“机构id为99的所有学生信息”,读到10条数据;这时候事务1又新增了一条数据,当事务2再次读取时就会发现变成11条数据;
#、什么是锁?
锁的本质是一个数据块。首先要知道,数据表的每条数据本身没有锁,“加锁”就是在内存中创建“一个数据块”来标记是哪一条数据正在被使用,这样当其它线程对这条数据进行改动时,会先从内存中找“这条记录是不是被使用?”,以此来判断自己是否需要等待。
两种情形下,当事务加锁后需要解决数据一致性的问题:
情形一:写 —— 写;
解决方法:加锁
情形二:读 —— 写;
解决方法:方法一,读操作使用MVCC(多版本并发控制/快照/事务隔离级别),写操作进行加锁;方法二,读写操作都进行加锁
#、数据库表创建注意事项
1、字段名及字段配制合理性
-
剔除关系不密切的字段;
-
字段命名要有规则及相对应的含义(不要一部分英文,一部分拼音,还有类似a.b.c这样不明含义的字段);
-
字段命名尽量不要使用缩写(大多数缩写都不能明确字段含义);
-
字段不要大小写混用(想要具有可读性,多个英文单词可使用下划线形式连接);
-
字段名不要使用保留字或者关键字;
-
保持字段名和类型的一致性;
-
慎重选择数字类型;
-
给文本字段留足余量;
2、系统特殊字段处理及建成后建议
-
添加删除标记(例如操作人、删除时间);
-
建立版本机制;
3、表结构合理性配置
-
多型字段的处理,就是表中是否存在字段能够分解成更小独立的几部分(例如:人可以分为男人和女人);
-
多值字段的处理,可以将表分为三张表,这样使得检索和排序更加有调理,且保证数据的完整性!
4、其它建议
-
对于大数据字段,独立表进行存储,以便影响性能(例如:简介字段);
-
使用varchar类型代替char,因为varchar会动态分配长度,char指定长度是固定的;
-
给表创建主键,对于没有主键的表,在查询和索引定义上有一定的影响;
-
避免表字段运行为null,建议设置默认值(例如:int类型设置默认值为0)在索引查询上,效率立显;
-
建立索引,最好建立在唯一和非空的字段上,建立太多的索引对后期插入、更新都存在一定的影响(考虑实际情况来创建);
#、Mysql中有哪些不同的表格?
共有5种类型的表格:MyISAM、Heap、Merge、INNODB、ISAM
写出三种以上MySQL数据库存储引擎的名称(提示:不区分大小写)
MyISAM、InnoDB、BDB(BerkeleyDB)、Merge、Memory(Heap)、Example、Federated、Archive、CSV、Blackhole、MaxDB 等等十几个引擎
在 MySQL5.1 以及之前的版本,默认的存储引擎是 MyISAM ,但是目前已经不再更新,且它有几个比较关键的缺点:
- 不支持事务。
- 使用表级锁,如果数据量大,一个插入操作锁定表后,其他请求都将阻塞。
#、简述在MySQL数据库中MyISAM和InnoDB的区别?
1.MyISAM 是非事务的存储引擎,适合用于频繁查询的应用。
表锁,不会出现死锁,适合小数据,小并发。
2.innodb是支持事务的存储引擎,合于插入和更新操作比较多的应用
,设计合理的话是行锁(最大区别就在锁的级别上),适合大数据,大并发。
MyISAM:
- 不支持事务,但是每次查询都是原子的;
- 支持表级锁,即每次操作是对整个表加锁;
- 存储表的总行数;
- 一个MYISAM表有三个文件:索引文件、表结构文件、数据文件;
- 采用菲聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
InnoDb:
- 支持ACID的事务,支持事务的四种隔离级别;
- 支持行级锁及外键约束:因此可以支持写并发;
- 不存储总行数;
如何选择合适的存储引擎?
提供几个选择标准,然后按照标准,选择对应的存储引擎即可,也可以根据 常用引擎对比 来选择你使用的存储引擎。使用哪种引擎需要根据需求灵活选择,一个数据库中多个表可以使用不同的引擎以满足各种性能和实际需求。使用合适的存储引擎,将会提高整个数据库的性能。
- 是否需要支持事务。
- 对索引和缓存的支持。
- 是否需要使用热备。
- 崩溃恢复,能否接受崩溃。
- 存储的限制。
- 是否需要外键支持。
#、myisam chk是用来做什么的?
它是用来压缩MyISAM表,这减少磁盘或内存使用。
MyISAM Static和MyISAM Dynamic有什么区别?
在MyISAM Static上的所有字段有固定宽度。动态MyISAM表将具有像TEXT,BLOB等字段,以适应不同长度的数据类型。
MyISAM Static在受损情况下更容易恢复。
#、如果有一个表一列定义为TIMESTAMP,将发生什么?
每当行被更改时,时间戳字段将获取当前时间戳。
列设置为AUTO INCREMENT时,如果在表中达到最大值,会发生什么情况?
它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。
怎样才能找出最后一次插入时分配了哪个自动增量?
LAST_INSERT_ID将返回由Auto_increment分配的最后一个值,并且不需要指定表名称。
#、CHAR和VARCHAR的区别?
- CHAR和VARCHAR类型在存储和检索方面有所不同
- CHAR列长度固定为创建表时声明的长度,长度值范围是1到255
- 当CHAR值被存储时,它们被用空格填充到特定长度,检索CHAR值时需删除尾随空格。
- 一个InnoDb引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为2G),受操作系统文件大小的限制;
- 主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整。
50道MySQL面试题,掌握之后你将获得无上法力,一发不可收拾!_谦卑t的博客-CSDN博客
#、NOW()和CURRENT_DATE()有什么区别?
- NOW()命令用于显示当前年份,月份,日期,小时,分钟和秒。
- CURRENT_DATE()仅显示当前年份,月份和日期。
#、mysql语句,如何优化DISTINCT?
DISTINCT在所有列上转换为GROUP BY,并与ORDER BY子句结合使用。
SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;
#、BLOB 和 TEXT 有什么区别?
- BLOB是一个二进制对象,可以容纳可变数量的数据。TEXT是一个不区分大小写的BLOB。
- BLOB和TEXT类型之间的唯一区别在于对BLOB值进行排序和比较时区分大小写,对TEXT值不区分大小写。
#、如何查看为表格定义的所有索引?
SHOW INDEX FROM <tablename>;
#、如何进行SQL优化?
答:(1)选择正确的存储引擎
以 MySQL为例,包括有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。但是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
(2)优化字段的数据类型
记住一个原则,越小的列会越快。如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。当然,你也需要留够足够的扩展空间。
(3)为搜索字段添加索引
索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么最好是为其建立索引,除非你要搜索的字段是大的文本字段,那应该建立全文索引。
(4)避免使用Select *从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。即使你要查询数据表的所有字段,也尽量不要用*通配符,善用内置提供的字段排除定义也许能给带来更多的便利。
(5)使用 ENUM 而不是 VARCHAR
ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。例如,性别、民族、部门和状态之类的这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。
(6)尽可能的使用 NOT NULL
除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。 NULL其实需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。
(7)固定长度的表会更快
如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理。
固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。
并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间。
#、如何设计一个高并发的系统
- 数据库的优化,包括合理的事务隔离级别、SQL语句优化、索引的优化
- 使用缓存,尽量减少数据库 IO
- 分布式数据库、分布式缓存
- 服务器的负载均衡
锁的优化策略
- 读写分离
- 分段加锁
- 减少锁持有的时间
- 多个线程尽量以相同的顺序去获取资源
什么情况下设置了索引但无法使用
- ① 以“%”开头的LIKE语句,模糊匹配
- ② OR语句前后没有同时使用索引
- ③ 数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int型)
优化数据库的方法
- 选取最适用的字段属性,尽可能减少定义字段宽度,尽量把字段设置NOTNULL,例如’省份’、’性别’最好适用ENUM
- 使用连接(JOIN)来代替子查询
- 适用联合(UNION)来代替手动创建的临时表
- 事务处理
- 锁定表、优化事务处理
- 适用外键,优化锁定表
- 建立索引
- 优化查询语句
为表中得字段选择合适得数据类型(物理设计)
字段类型优先级: 整形>date,time>enum,char>varchar>blob,text
优先考虑数字类型,其次是日期或者二进制类型,最后是字符串类型,同级别得数据类型,应该优先选择占用空间小的数据类型
mysql面试题_Kobe__Bryant__的博客-CSDN博客
#、用什么来确保表格里的字段只接受特定范围里的值?
- Check限制,它在数据库表格里被定义,用来限制输入该列的值。
- 触发器也可以被用来限制数据库表格里的字段能够接受的值,但是这种办法要求触发器在表格里被定义,这可能会在某些情况下影响到性能。
#、如何通俗地理解三个范式?
- 第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
- 第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
- 第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。。
范式化设计优缺点:
- 优点:可以尽量得减少数据冗余,使得更新快,体积小
- 缺点:对于查询需要多个表进行关联,减少写得效率增加读得效率,更难进行索引优化
反范式化:
- 优点:可以减少表得关联,可以更好得进行索引优化
- 缺点:数据冗余以及数据异常,数据得修改需要更多的成本
#、解释MySQL外连接、内连接与自连接的区别
先说什么是交叉连接: 交叉连接又叫笛卡尔积,它是指不使用任何条件,直接将一个表的所有记录和另一个表中的所有记录一一匹配。
内连接 则是只有条件的交叉连接,根据某个条件筛选出符合条件的记录,不符合条件的记录不会出现在结果集中,即内连接只连接匹配的行。
外连接 其结果集中不仅包含符合连接条件的行,而且还会包括左表、右表或两个表中的所有数据行,这三种情况依次称之为左外连接,右外连接,和全外连接。
左外连接,也称左连接,左表为主表,左表中的所有记录都会出现在结果集中,对于那些在右表中并没有匹配的记录,仍然要显示,右边对应的那些字段值以NULL来填充。右外连接,也称右连接,右表为主表,右表中的所有记录都会出现在结果集中。左连接和右连接可以互换,MySQL目前还不支持全外连接。
#、了解XSS攻击吗?
XSS是跨站脚本攻击,首先是利用跨站脚本漏洞以一个特权模式去执行攻击者构造的脚本,然后利用不安全的Activex控件执行恶意的行为。
如何防止?
使用htmlspecialchars()函数对提交的内容进行过滤,使字符串里面的特殊符号实体化。
#、索引,主键,唯一索引,联合索引的区别
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。
普通索引允许被索引的数据列包含重复的值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。也就是说,唯一索引可以保证数据记录的唯一性。
主键,是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字 PRIMARY KEY 来创建。
索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引,这就是联合索引。
索引可以极大的提高数据的查询速度,但是会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件。
- 1、普通索引:最基本的索引,没有任何约束。
- 2、唯一索引:与普通索引类似,但具有唯一性约束。
- 3、主键索引:特殊的唯一索引,不允许有空值。
- 4、复合索引:将多个列组合在一起创建索引,可以覆盖多个列。
- 5、外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作。
- 6、全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,并且只能对英文进行全文检索,一般使用全文索引引擎。
视图
#、试述视图的优点?
- (1) 视图能够简化用户的操作
- (2) 视图使用户能以多种角度看待同一数据;
- (3) 视图为数据库提供了一定程度的逻辑独立性;
- (4) 视图能够对机密数据提供安全保护。
存储过程
#、什么是存储过程?用什么来调用?
- 存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。
- 可以用一个命令对象来调用存储过程。
-- 查看hbedu下有哪些存储过程;
show procedure status where db='hbedu';
SHOW CREATE PROCEDURE hbedu.pro_lud;
-- 修改存储过程??????
ALTER PROCEDURE
-- 删除存储过程
DROP PROCEDURE pro_lud2;
call pro_lud(@asd);
call pro_lud2(@asd);
call pro_lud3(@asd);
select @asd
delimiter $$
create procedure pro_lud3(in idd int)
begin
set idd=11;
select idd;
end
$$
delimiter ;
-- delimiter $$
-- create procedure pro_lud2(out idd int)
-- begin
-- set idd=11;
-- select idd;
-- end
-- $$
-- delimiter ;
-- delimiter $$
-- create procedure pro_lud(inout p_inout int)
-- begin
-- select p_inout;
-- set p_inout=112;
-- select p_inout;
-- end
-- $$
-- DELIMITER ;
事务
#、Mysql中InnoDB支持的四种事务隔离级别名称,以及逐级之间的区别?
SQL标准定义的四个隔离级别为:
-
Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
-
Repeatable read (可重复读):可避免脏读、不可重复读的发生。
-
Read committed (读已提交):可避免脏读的发生。
-
Read uncommitted (读未提交):最低级别,任何情况都无法保证。
#、数据库中的事务是什么?
事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消。ACID 四大特性,原子性、隔离性、一致性、持久性。
#、事务的特性指的是?
- 原子性 Atomicity :一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
- 一致性 Consistency :在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
- 隔离性 Isolation :数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性 Durability :事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
#、事务的并发问题?
实际场景下,事务并不是串行的,所以会带来如下三个问题:
**脏读(Dirty read):**当一个事务正在访问数据并且对其进行了修改,但是还没提交事务,这时另外一个事务也访问了这个数据,然后使用了这个数据,因为这个数据的修改还没提交到数据库,所以另外一个事务读取的数据就是“脏数据”,这种行为就是“脏读”,依据“脏数据”所做的操作可能是会出现问题的。
修改丢失(Lost of modify):是指一个事务读取一个数据时,另外一个数据也访问了该数据,那么在第一个事务修改了这个数据之后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,这种情况就被称为修改丢失。例如:事务1读取表中数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果都是19,但是事务1的修改记录丢失了。
不可重复读(Unrepeatableread):指在一个事务内多次读取同一数据,在这个事务还没结束时,另外一个事务也访问了这个数据并对这个数据进行了修改,那么就可能造成第一个事务两次读取的数据不一致,这种情况就被称为不可重复读。
幻读(Phantom read):幻读与不可重复读类似,幻读是指一个事务读取了几行数据,这个事务还没结束,接着另外一个事务插入了一些数据,在随后的查询中,第一个事务读取到的数据就会比原本读取到的多,就好像发生了幻觉一样,所以称为幻读。
#、【重点】请说说 MySQL 的四种事务隔离级别?
mysql默认的事务隔离级别为repeatable-read

| 事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
| 读未提交(read-uncommitted) | 是 | 是 | 是 |
| 不可重复读(read-committed) | 否 | 是 | 是 |
| 可重复读(repeatable-read) | 否 | 否 | 是 |
| 串行化(serializable) | 否 | 否 | 否 |
- 1、插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于 InnoDB 表,我们一般都会定义一个自增的 ID 列为主键。
- 关于这一点,可能面试官会换一个问法。例如,为什么主键需要是自增 ID ,又或者为什么主键需要带有时间性关联。
- 2、更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB 表,我们一般定义主键为不可更新。
- MySQL 默认情况下,主键是允许更新的。对于 MongoDB ,其 主键是不允许更新的。
- 3、二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
- 当然,有一种情况可以无需二次查找,基于非主键索引查询,但是查询字段只有主键 ID ,那么在二级索引中就可以查找到。
- 4、主键 ID 建议使用整型。因为,每个主键索引的 B+Tree 节点的键值可以存储更多主键 ID ,每个非主键索引的 B+Tree 节点的数据可以存储更多主键 ID 。
锁
#、Mysql中有哪几种锁?
- 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
- 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
MySQL 面试题_木村牧村的博客-CSDN博客_mysql面试题
#、请说说 MySQL 的锁机制?
表锁是日常开发中的常见问题,因此也是面试当中最常见的考察点,当多个查询同一时刻进行数据修改时,就会产生并发控制的问题。MySQL 的共享锁和排他锁,就是读锁和写锁。
共享锁:不堵塞,多个用户可以同时读一个资源,互不干扰。
排他锁:一个写锁会阻塞其他的读锁和写锁,这样可以只允许一个用户进行写入,防止其他用户读取正在写入的资源。
锁的粒度
- 表锁:系统开销最小,会锁定整张表,MyIsam 使用表锁。
- 行锁:最大程度的支持并发处理,但是也带来了最大的锁开销,InnoDB 使用行锁。
#、什么是悲观锁?什么是乐观锁
1)悲观锁
它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
在悲观锁的情况下,为了保证事务的隔离性,就需要一致性锁定读。读取数据时给加锁,其它事务无法修改这些数据。修改删除数据时也要加锁,其它事务无法读取这些数据。
2)乐观锁
相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。
而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
什么是死锁?
多数情况下,可以认为如果一个资源被锁定,它总会在以后某个时间被释放。而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。简单的说,进程 A 等待进程 B 释放他的资源,B 又等待 A 释放他的资源,这样就互相等待就形成死锁。
虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件:
互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合 {P0,P1,P2,•••,Pn} 中的 P0 正在等待一个 P1 占用的资源;P1 正在等待 P2 占用的资源,……,Pn 正在等待已被 P0 占用的资源。
下列方法有助于最大限度地降低死锁:
- 设置获得锁的超时时间。通过超时,至少保证最差最差最差情况下,可以有退出的口子。
- 按同一顺序访问对象。这个是最重要的方式。
- 避免事务中的用户交互。
- 保持事务简短并在一个批处理中。
- 使用低隔离级别。
- 使用绑定连接。
本文围绕MySQL面试展开,涵盖count函数区别、SQL语法与优化、术语解释、存储引擎、字段类型、事务、锁等内容。介绍了不同存储引擎特点及选择标准,阐述事务特性、并发问题和隔离级别,还讲解了各种锁机制及死锁预防方法。

1662

被折叠的 条评论
为什么被折叠?



