MySql

基本概念

MySQL有哪些数据库类型?

数值类型

有包括 tinyint、smallint、mediumint、int、bigint,分别表⽰ 1 字节、2 字节、3 字节、4 字节、8 字节的整数类型。

任何整数类型都可以加上 unsigned 属性,表⽰⽆符号整数。

任何整数类型都可以指定长度,但它不会限制数据的合法长度,仅仅限制了显⽰长度。

还有包括 FLOAT、DOUBLE、DECIMAL 在内的⼩数类型。

字符串类型

包括 VARCHAR、CHAR、TEXT、BLOB。

注意:VARCHAR(n) 和 CHAR(n) 中的 n 并不代表字节个数,⽽是代表字符的个数。

⽇期和时间类型

常⽤于表⽰⽇期和时间类型为 DATETIME、DATE 和 TIMESTAMP。

尽量使⽤ TIMESTAMP,空间效率⾼于 DATETIME。

CHAR 和 VARCHAR 区别?

1、⾸先可以明确的是 CHAR 是定长的,⽽ VARCHAR 是可以变长。

CHAR 会根据声明的字符串长度分配空间,并会使⽤空格对字符串右边进⾏尾部填充。所以在检索 CHAR 类型数
据时尾部空格会被删除,如保存的是字符串 'char ’ ,但最后查询到的是 ‘char’ 。又因为长度固定,所以存储效率⾼于 VARCHAR 类型。

VARCHAR 在 MySQL 5.0 之后长度⽀持到 65535 字节,但会在数据开头使⽤额外 1~2 个字节存储字符串长度(列
长度⼩于 255 字节时使⽤ 1 字节表⽰,否则 2 字节),在结尾使⽤ 1 字节表⽰字符串结束。

2、再者,在存储⽅式上,CHAR 对英⽂字符(ASCII)占⽤ 1 字节,对⼀个汉字使⽤2 字节。⽽ VARCHAR 对每个字符均使⽤ 2 字节。

虽然 VARCHAR 是根据字符串长度分配存储空间的,但在内存中依旧使⽤声明长度进⾏排序等作业,故在使⽤时仍需综合考量字段长度。

CHAR 和 VARCHAR 如何选择?

1、长度区别

Char 范围是 0~255。

Varchar 最长是 64k(注意这⾥的 64k 是整个 row 的长度,要考虑到其它的 column,还有如果存在 not null 的时候也会占⽤⼀位,对不同的字符集,有效长度还不⼀样,⽐如 utf-8 的,最多 21845,还要除去别的column),但 Varchar 在⼀般情况下存储都够⽤了。

如果遇到了⼤⽂本,考虑使⽤ Text,最⼤能到 4G(其中 TEXT 长度 65,535 bytes,约 64kb;MEDIUMTEXT 长度 16,777,215 bytes,约 16 Mb;⽽ LONGTEXT 长度 4,294,967,295 bytes,约 4Gb)。

2、效率区别

效率来说基本是 Char > Varchar > Text,但是如果使⽤的是 Innodb 引擎的话,推荐使⽤ Varchar 代替 Char。

3、默认值区别

Char 和 Varchar ⽀持设置默认值,⽽ Text 不能指定默认值。

数据库设计

什么是三⼤范式?

第⼀范式(1NF):字段(或属性)是不可分割的最⼩单元,即不会有重复的列,体现原⼦性
第⼆范式(2NF):满⾜ 1NF 前提下,存在⼀个候选码,⾮主属性全部依赖该候选码,即存在主键,体现唯⼀
性,专业术语则是消除部分函数依赖
第三范式(3NF):满⾜ 2NF 前提下,⾮主属性必须互不依赖,消除传递依赖

除了三⼤范式外,还有BC范式和第四范式,但其规范过于严苛,在⽣产中往往使⽤不到。

什么是范式和反范式,以及各⾃优缺点?

范式是符合某⼀种级别的关系模式的集合。构造数据库必须遵循⼀定的规则。在关系数据库中,这种规则就是范式。

名称优点缺点
范式范式化的表减少了数据冗余,数据表更新操作快、占⽤存储空间少。查询时通常需要多表关联查询,更难进⾏索引优化
反范式反范式的过程就是通过冗余数据来提⾼查询性能,可以减少表关联和更好进⾏索引优化存在⼤量冗余数据,并且数据的维护成本更⾼

所以在平时⼯作中,我们通常是将范式和反范式相互结合使⽤。

简单说一说drop、delete与truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别

delete和truncate只删除表的数据不删除表的结构 速度,一般来说: drop> truncate >delete delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效; 如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚.操作不触发trigger.

说说在 MySQL 中一条查询 SQL 是如何执行的?

在这里插入图片描述

1)连接器
连接器负责跟客户端建⽴连接、获取权限、维持和管理连接。如果⽤户名密码验证通过后,连接器会到权限表⾥⾯查出你拥有的权限。之后该连接的权限验证都依赖于刚查出来的权限,即 Session 级。
MySQL 既⽀持短连接,也⽀持长连接。短连接就是操作完毕以后,马上 close 掉。保持长连接会消耗内存。长时间不活动的连接,默认 8 ⼩时断开。同时可以使⽤ mysql_reset_connection 重置连接资源⽽⽆需重新建⽴连接。
2)查询缓存
当获取连接后,⼀条 SELECT 语句会先去查询缓存,看之前是否执⾏过。如果获取到缓存后就执⾏返回,不然继续后⾯的步骤。

⼤多数时候不建议使⽤缓存,因为只要⼀个表更新,这个表上的所有缓存数据就会被清空了。对于那些经常更新的表来说,缓存命中率很低。MYSQL8版本直接将查询缓存的整块功能删掉了。
3)分析器
分析器先会做词法分析,MySQL 需要识别出 SQL 语句中的字符串分别是什么,代表什么。再做语法分析,根据词法分析的结果,判断 SQL 语句是否满⾜ MySQL 语法。

4)优化器
优化器会对 SQL 的执⾏顺序,使⽤哪个索引进⾏优化,确定 SQL 的执⾏⽅案。
5)执⾏器
执⾏器执⾏ SQL 语句会对权限进⾏校验,如果有权限,就打开表继续执⾏。打开表的时候,执⾏器就会根据表的引擎定义,去使⽤这个引擎提供的接口。

MySQL中,如何定位慢查询?

嗯~,我们当时做压测的时候有的接口非常的慢,接口的响应时间超过了2秒以上,因为我们当时的系统部署了运维的监控系统Skywalking ,在展示的报表中可以看到是哪一个接口比较慢,并且可以分析这个接口哪部分比较慢,这里可以看到SQL的具体的执行时间,所以可以定位是哪个sql出了问题

如果,项目中没有这种运维的监控系统,其实在MySQL中也提供了慢日志查询的功能,可以在MySQL的系统配置文件中开启这个慢日志的功能,并且也可以设置SQL执行超过多少时间来记录到一个日志文件中,我记得上一个项目配置的是2秒,只要SQL执行的时间超过了2秒就会记录到日志文件中,我们就可以在日志文件找到执行比较慢的SQL了。

那这个SQL语句执行很慢, 如何分析呢?

  1. 如果一条sql执行很慢的话,
  2. 第一:我们通常会使用mysql自动的执行计划explain来去查看这条sql的执行情况,比如在这里面可以通过key和key_len检查是否命中了索引,如果本身已经添加了索引,也可以判断索引是否有失效的情况
  3. 第二个,可以通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
  4. 第三个可以通过extra建议来判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复

索引

索引的定义

索引在项目中还是比较常见的,它是帮助MySQL高效获取数据的数据结构,主要是用来提高数据检索的效率,降低数据库的IO成本,同时通过索引列对数据进行排序,降低数据排序的成本,也能降低了CPU的消耗,其实在生活中索引的使用无处不在,比如说:书本里的目录;读书时的座位号,考试编号都有类似索引的功能;

总结来所有通过某规则数据结构和实际目标关联,根据特定规则算法快速寻址的功能都可以称之为索引;

索引的⼏种类型或分类?

1、从物理结构上可以分为聚集索引和⾮聚集索引两类:

聚簇索引:主要是指数据与索引放到一块,B+树的叶子节点保存了整行数据,有且只有一个,一般情况下主键在作为聚簇索引;

⾮聚簇索引:指的是数据与索引分开存储,B+树的叶子节点保存对应的主键,可以有多个,一般我们自己定义的索引都是非聚簇索引

2、从应⽤上可以划分为⼀下⼏类:

普通索引:MySQL 中的基本索引类型,没有什么限制,允许在定义索引的列中插⼊重复值和空值,纯粹为了提⾼查询效率。通过 ALTER TABLE table_name ADD INDEX index_name (column) 创建;

唯⼀索引:索引列中的值必须是唯⼀的,但是允许为空值。通过 ALTER TABLE table_name ADD UNIQUE index_name (column) 创建;

主键索引:特殊的唯⼀索引,也是聚簇索引,不允许有空值,并由数据库帮我们⾃动创建;

组合索引:组合表中多个字段创建的索引,遵守最左前缀匹配规则;

全⽂索引:只有在 MyISAM 引擎上才能使⽤,同时只⽀持 CHAR、VARCHAR、TEXT 类型字段上使⽤。

索引的优缺点?

优点

  • 通过创建唯⼀性索引,可以保证数据库表中每⼀⾏数据的唯⼀性。
  • 可以⼤⼤加快数据的检索速度,这也是创建索引的最主要的原因。
  • 可以加速表和表之间的连接,特别是在实现数据的参考完整性⽅⾯特别有意义。
  • 在使⽤分组和排序⼦句进⾏数据检索时,同样可以显著减少查询中分组和排序的时间。
  • 通过使⽤索引,可以在查询的过程中,使⽤优化隐藏器,提⾼系统的性能。

缺点

  • 创建和维护索引需要耗费时间,这种时间随着数据量的增加⽽增加,这样就降低了数据的维护速度。
  • 索引需要占物理空间,除了数据表占数据空间之外,每⼀个索引还要占⼀定的物理空间。如果要建⽴聚簇索引,那么需要的空间就会更⼤。

索引设计原则?

1、选择唯⼀性索引;

唯⼀性索引的值是唯⼀的,可以更快速的通过该索引来确定某条记录。

2、为常作为查询条件的字段建⽴索引;

如果某个字段经常⽤来做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建⽴索引,可以提⾼整个表的查询速度。

3、为经常需要排序、分组和联合操作的字段建⽴索引;

经常需要 ORDER BY、GROUP BY、DISTINCT 和 UNION 等操作的字段,排序操作会浪费很多时间。如果为其建⽴索引,可以有效地避免排序操作。

4、限制索引的数⽬;

每个索引都需要占⽤用磁盘空间,索引越多,需要的磁盘空间就越大,修改表时,对索引的重构和更新很麻烦。

5、⼩表不建议索引(如数量级在百万以内)

由于数据较⼩,查询花费的时间可能⽐遍历索引的时间还要短,索引可能不会产⽣优化效果。

6、尽量使用数据量少的索引

如果索引的值很长,那么查询的速度会受到影响。此时尽量使用前缀索引

7、删除不再使⽤或者很少使⽤的索引。

索引的数据结构?

索引的数据结构和具体存储引擎的实现有关,MySQL 中常⽤的是 Hash 和 B+ 树索引。

  • Hash 索引底层就是 Hash 表,进⾏查询时调⽤ Hash 函数获取到相应的键值(对应地址),然后回表查询获得实际数据.
  • B+ 树索引底层实现原理是多路平衡查找树,对于每⼀次的查询都是从根节点出发,查询到叶⼦节点⽅可以获得所查键值,最后查询判断是否需要回表查询.

Hash 和 B+ 树索引的区别?

Hash
1)Hash 进⾏等值查询更快,但⽆法进⾏范围查询。因为经过 Hash 函数建⽴索引之后,索引的顺序与原顺序⽆法保持⼀致,故不能⽀持范围查询。同理,也不⽀持使⽤索引进⾏排序。
2)Hash 不⽀持模糊查询以及多列索引的最左前缀匹配,因为 Hash 函数的值不可预测,如 AA 和 AB 的算出的值没有相关性。
3)Hash 任何时候都避免不了回表查询数据.

4)虽然在等值上查询效率⾼,但性能不稳定,因为当某个键值存在⼤量重复时,产⽣ Hash 碰撞,此时查询效率反⽽可能降低。

B+ Tree

1)B+ 树本质是⼀棵查找树,⾃然⽀持范围查询和排序。
2)在符合某些条件(聚簇索引、覆盖索引等)时候可以只通过索引完成查询,不需要回表。
3)查询效率⽐较稳定,因为每次查询都是从根节点到叶⼦节点,且为树的⾼度。

为何使⽤ B+ 树⽽⾮⼆叉查找树做索引?

  1. 我们知道⼆叉树的查找效率为 O(logn),当树过⾼时,查找效率会下降。另外由于我们的索引⽂件并不⼩,所以是存储在磁盘上的。
  2. ⽂件系统需要从磁盘读取数据时,⼀般以页为单位进⾏读取,假设⼀个页内的数据过少,那么操作系统就需要读取更多的页,涉及磁盘随机 I/O 访问的次数就更多。将数据从磁盘读⼊内存涉及随机 I/O 的访问,是数据库⾥⾯成本最⾼的操作之⼀。
  3. 因⽽这种树⾼会随数据量增多急剧增加,每次更新数据又需要通过左旋和右旋维护平衡的⼆叉树,不太适合⽤于存储在磁盘上的索引⽂件。

为何使⽤ B+ 树⽽⾮ B 树做索引?

在此之前,先来了解⼀下 B+ 树和 B 树的区别:

  • B 树⾮叶⼦结点和叶⼦结点都存储数据,因此查询数据时,时间复杂度最好为 O(1),最坏为 O(log n)。⽽ B+ 树只在叶⼦结点存储数据,⾮叶⼦结点存储关键字,且不同⾮叶⼦结点的关键字可能重复,因此查询数据时,时间复杂度固定为 O(log n)。
  • B+ 树叶⼦结点之间⽤链表相互连接,因⽽只需扫描叶⼦结点的链表就可以完成⼀次遍历操作,B 树只能通过中序遍历。

为什么 B+ 树⽐ B 树更适合应⽤于数据库索引?

B+ 树减少了 IO 次数。
由于索引⽂件很⼤因此索引⽂件存储在磁盘上,B+ 树的⾮叶⼦结点只存关键字不存数据,因⽽单个页可以存储更多的关键字,即⼀次性读⼊内存的需要查找的关键字也就越多,磁盘的随机 I/O 读取次数相对就减少了。
B+ 树查询效率更稳定
由于数据只存在在叶⼦结点上,所以查找效率固定为 O(log n),所以 B+ 树的查询效率相⽐B树更加稳定。
B+ 树更加适合范围查找
B+ 树叶⼦结点之间⽤链表有序连接,所以扫描全部数据只需扫描⼀遍叶⼦结点,利于扫库和范围查询;B 树由于⾮叶⼦结点也存数据,所以只能通过中序遍历按序来扫。也就是说,对于范围查询和有序遍历⽽⾔,B+ 树的效率更⾼。

知道什么是回表查询嘛 ?

嗯,其实跟刚才介绍的聚簇索引和非聚簇索引是有关系的,回表的意思就是通过二级索引找到对应的主键值,然后再通过主键值找到聚集索引中所对应的整行数据,这个过程就是回表

备注:如果面试官直接问回表,则需要先介绍聚簇索引和非聚簇索引

知道什么叫覆盖索引嘛 ?

覆盖索引是指select查询语句使用了索引,在返回的列,必须在索引中全部能够找到,如果我们使用id查询,它会直接走聚集索引查询,一次索引扫描,直接返回数据,性能高。

MYSQL超大分页怎么处理 ?

嗯,**超大分页**一般都是在数据量比较大时,我们使用了limit分页查询,并且需要对数据进行排序,这个时候效率就很低,我们可以采用覆盖索引子查询来解决

先分页查询数据的id字段,确定了id之后,再用子查询来过滤,只查询这个id列表中的数据就可以了

因为查询id的时候,走的覆盖索引,所以效率可以提升很多

索引创建原则有哪些?

嗯,这个情况有很多,不过都有一个大前提,就是表中的数据要超过10万以上,我们才会创建索引,并且添加索引的字段是查询比较频繁的字段,一般也是像作为查询条件,排序字段或分组的字段这些。

还有就是,我们通常创建索引的时候都是使用复合索引来创建,一条sql的返回值,尽量使用覆盖索引,如果字段的区分度不高的话,我们也会把它放在组合索引后面的字段。

如果某一个字段的内容较长,我们会考虑使用前缀索引,当然并不是所有的字段都要添加索引,这个索引的数量也要控制,因为添加索引也会导致新增改的速度变慢。

什么情况下索引会失效 ?

嗯,这个情况比较多,我说一些自己的经验,以前遇到过的

比如,第一个是,索引在使用的时候没有遵循最左匹配原则,第二个是,模糊查询,如
果%号在前面也会导致索引失效。第三个是,如果在添加索引的字段上进行了运算操作
或者类型转换也都会导致索引失效。

我们之前还遇到过一个就是,如果在使用复合索引时,中间使用了范围查询,右边的条件索引也会失效

所以,通常情况下,想要判断出这条sql是否有索引失效的情况,可以使用explain执行计划来分析

sql的优化的经验

1、查询语句中不要使用select *
2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union all会更好)
5、应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。
6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0

那在使用索引的时候,是如何优化呢?

参考索引创建原则

事务

事务的特性是什么?可以详细说一下吗?

嗯,这个比较清楚,ACID,分别指的是:原子性、一致性、隔离性、持久性;我举个例子:

A向B转账500,转账成功,A扣除500元,B增加500元,原子操作体现在要么都成功,要么都失败

在转账的过程中,数据要一致,A扣除了500,B必须增加500

在转账的过程中,隔离性体现在A向B转账,不能受其他事务干扰

在转账的过程中,持久性体现在事务提交后,要把数据持久化(可以说是落盘操作)

并发事务带来哪些问题?

我们在项目开发中,多个事务并发进行是经常发生的,并发也是必然的,有可能导致一些问题

第一是脏读, 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

第二是不可重复读:比如在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

第三是幻读(Phantom read):幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

怎么解决这些问题呢?MySQL的默认隔离级别是?

解决方案是对事务进行隔离

MySQL InnoDB 存储引擎的默认支持的隔离级别是 可重读

MySQL支持四种隔离级别,分别有:

读取未提交: 最低的隔离级别,允许读取尚未提交的数据变更,可
能会导致脏读、幻读或不可重复读。

读取已提交: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。

可重复读: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

可串行化: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

undo log和redo log的区别

好的,其中redo log日志记录的是数据页的物理变化,服务宕机可用来同步数据,而undo log 不同,它主要记录的是逻辑日志,当事务回滚时,通过逆操作恢复原来的数据,比如我们删除一条数据的时候,就会在undo log日志文件中新增一条delete语句,如果发生回滚就执行逆操作;

redo log保证了事务的持久性,undo log保证了事务的原子性和一致性

事务中的隔离性是如何保证的呢?(你解释一下MVCC)

事务的隔离性是由锁和mvcc实现的。

其中mvcc的意思是多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,它的底层实现主要是分为了三个部分,第一个是隐藏字段第二个是undo log日志,第三个是readView读视图

隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事务id),记录每一次操作的事务id,是自增的;另一个字段是roll_pointer(回滚指针),指向上一个版本的事务版本记录地址

undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表

readView解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读是不一样的,最终的访问的结果不一样。如果是rc隔离级别,每一次执行快照读时生成ReadView,如果是rr隔离级别仅在事务中第一次执行快照读时生成ReadView,后续复用

MySQL主从同步原理

MySQL主从复制的核心就是二进制日志(DDL(数据定义语言)语句和 DML(数据操纵语言)语句),它的步骤是这样的:

第一:主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。

第二:从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志Relay Log 。

第三:从库重做中继日志中的事件,将改变反映它自己的数据

请说说 MySQL 数据库的锁?

MySQL 中有共享锁和排它锁,也就是读锁和写锁。

  1. 共享锁:不堵塞,多个用户可以同一时刻读取同一个资源,相互之间没有影响。
  2. 排它锁:一个写操作阻塞其他的读锁和写锁,这样可以只允许一个用户进行写入,防止其他用户读取正在写入的资源。
  3. 表锁:系统开销最小,会锁定整张表,MyISAM 使用表锁。
  4. 行锁:容易出现死锁,发生冲突概率低,并发高,InnoDB 支持行锁(必须有索引才能实现,否则会自动锁全表,那么就不是行锁了)。

说说什么是锁升级?

MySQL 行锁只能加在索引上,如果操作不走索引,就会升级为表锁。因为 InnoDB 的行锁是加在索引上的,如果不走索引,自然就没法使用行锁了,原因是 InnoDB 是将 primary key index和相关的行数据共同放在 B+ 树的叶节点。InnoDB 一定会有一个 primary key,secondary index 查找的时候,也是通过找到对应的 primary,再找对应的数据行。

当非唯一索引上记录数超过一定数量时,行锁也会升级为表锁。测试发现当非唯一索引相同的内容不少于整个表记录的二分之一时会升级为表锁。因为当非唯一索引相同的内容达到整个记录的二分之一时,索引需要的性能比全文检索还要大,查询语句优化时会选择不走索引,造成索引失效,行锁自然就会升级为表锁。

说说悲观锁和乐观锁

悲观锁
说的是数据库被外界(包括本系统当前的其他事物以及来自外部系统的事务处理)修改保持着保守态度,因此在整个数据修改过程中,将数据处于锁状态。悲观的实现往往是依靠数据库提供的锁机制,也只有数据库层面提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统汇总实现了加锁机制,也是没有办法保证系统不会修改数据。

在悲观锁的情况下,为了保证事务的隔离性,就需要一致性锁定读。读取数据时给加锁,其它事务无法修改这些数据。修改删除数据时也要加锁,其它事务无法读取这些数据。

乐观锁
相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。

而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

怎样尽量避免死锁的出现?

  1. 设置获取锁的超时时间,至少能保证最差情况下,可以退出程序,不至于一直等待导致死锁;
  2. 设置按照同一顺序访问资源,类似于串行执行;
  3. 避免事务中的用户交叉;
  4. 保持事务简短并在一个批处理中;
  5. 使用低隔离级别;
  6. 使用绑定链接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值