【shoppe面试准备】

数据库-锁

作用

保持数据一致性.当多个线程并发访问某个数据时,加锁,可以保证这个数据在任何时刻最多只有一个线程在访问,保证数据的完整性和一致性。

分类

表级锁

一次会将整个表锁定,所以可以很好的避免死锁问题

  1. 锁定粒度大,锁冲突概率高,并发度低
  2. 好处是不会出现死锁,开销小,获取锁和释放锁的速度很快
  3. 使用表级锁定的主要是MylSAM,MEMORY,CSV等一些非事务性存储引擎,适用于以查询为主,少量更新的应用

行级锁

  1. 好处是锁定对象的颗粒度很小,发声锁冲突的概率低、并发度高
  2. 缺点是开销大、加锁慢,容易发生死锁
  3. 使用行级锁定的主要是InnoDB存储引擎、及分布式存储引擎NDBCluster等。使用于对事务完整性要求较高的系统。
InnoDB行级锁类型
  1. 共享锁:又称读锁,简单讲就是多个事务对同一数据进行共享一把锁,都能访问到数据,但是只能读不能改。
  2. 排他锁;又称死锁,就是不能与其他锁共存,如一个事务获取了一个数据行的排他锁,其他事物就不能再获取该行的其他锁了,只有获取排他锁的事务可以对数据进行读取和修改。
  3. 意向锁:是InnoDB自动加的,不需要用户干预。不会与行级的共享/排他锁互斥。
注意
  1. 一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他锁,但是可以直接通过select…from…查询数据,因为普通查询没有任何锁机制。
  2. mysql InnoDB引擎中update,delete,insert语句自动加排他锁
    在这里插入图片描述
适用场景
  1. 共享锁适用于:用来确认某行记录是否存在,并确认没有人对这个记录进行update或者delete操作,如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁
  2. 排他锁适用于:锁定行记录后需要进行更新操作的应用

共享锁(S):SELECT * FROM table_name WHERE … LOCK IN SHARE MODE
排他锁(X):SELECT * FROM table_name WHERE … FOR UPDATE

为什么使用意向锁

1.事务 A 先获取了某一行的 排他锁 ,并未提交:

SELECT * FROM users WHERE id = 6 FOR UPDATE;

(1)事务 A 获取了 users 表上的 意向排他锁 。
(2)事务 A 获取了 id 为 6 的数据行上的 排他锁 。

2.事务 C 也想获取 users 表中某一行的 排他锁 :

SELECT * FROM users WHERE id = 5 FOR UPDATE;

(1)事务 C 申请 users 表的 意向排他锁 。
事务 C 检测到 事务 A 持有 users 表的 意向排他锁 。
因为意向锁之间并不互斥,所以 事务 C 获取到了 users 表的 意向排他锁 。
因为id 为 5 的数据行上不存在任何 排他锁 ,最终 事务 C 成功获取到了该数据行上的 排他锁 。

页面锁

页的粒度上进行锁定,锁定的数据资源比行锁要多,因为一个页中可以有多个行记录,当我们使用页锁的时候,会出现数据浪费的现象,页锁的开销介于表锁行锁之间。

  1. 介于行级锁和表级锁之间
  2. 会发生死锁
  3. BDB采用页面锁(page-level locking)或表级锁,默认为页面锁

关于锁的常见问题

  1. InnoDB存储引擎什么时候会锁住整张表(什么时候使用行级锁),什么时候或只锁住一行呢(使用行锁)?

只有通过索引条件查询数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁! 记住:一定要记住为匹配条件字段加索引。

  1. 什么时候使用行级锁?什么时候使用表级锁?

在增删改查时匹配的条件字段不带有索引时,innodb使用的是表级锁,

  1. 行级锁锁的是什么?行级锁怎么实现加锁?

(1)行级锁是针对索引加的锁;
(2) InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁来实现的。

  1. mysql读锁和写锁?

(1)因为只有触发了读写锁,我们才会谈是进行行级锁定还是进行表级锁定;
(2)用select 命令时触发读锁,当使用update,delete,insert时触发写锁,并且使用rollback或commit后解除本次锁定。

  1. 常见的锁算法:

next KeyLocks锁,同时锁住记录(数据),并且锁住记录前面的Gap
Gap锁,不锁记录,仅仅记录前面的Gap
Recordlock锁(锁数据,不锁Gap)
所以其实 Next-KeyLocks=Gap锁+ Recordlock锁

  1. 什么时候会释放锁?

提交事务或回滚事务就会释放锁。

数据库-索引

作用

是定义在table基础之上,有助于无需检查所有记录而快速定位所需记录的一种辅助存储结构,由一系列存储在磁盘上的索引项组成,每一种索引项由索引字段和行指针构成。

优点

1.通过创建索引,可以在查询的过程中,提高系统的性能;
2.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
3.在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的时间;

缺点

1.创建索引和维护索引要耗费时间,而且时间随着数据量的增加而增大;
2.索引需要占用物理空间,如果要建立聚簇索引,所需要的空间会更大;
3.在对表中的数据进行增加删除和修改时需要耗费较多的时间,因为索引也要动态地维护;

什么是稠密索引和稀疏索引?

稠密索引

对于主文件中每一个记录都对应一个索引项;

候选键属性的稠密索引

先查索引,然后再依据索引读主文件;

非候选键属性的稠密索引

1.主文件按索引字段排序,索引文件中的索引字段值无重复;
2.主文件索引字段未排序,但索引文件中的索引字段值是有重复的;
3.主文件索引字段未排序且索引文件中的索引字段值无重复,这时可以引入指针桶来处理;

稀疏索引

对于主文件中部分记录有索引项和它对应(要求主文件必须是按对应索引字段属性排序存储);

什么是主索引和辅助索引?
主索引

对每个存储块有一个索引项,每个存储块的第一个记录叫锚,通常建立在有序文件的基于主码的排序字段上,属于稀疏索引。

辅助索引

是定义在主文件的任一或多个非排序字段上的辅助存储结构,属于稠密索引。
一个主文件可以有一个主索引,但可以有多个辅助索引。

什么是聚簇索引和非聚簇索引?
聚簇索引

将数据存储与索引放到了一块,找到索引也就找到了数据,主文件按照对应字段排序存储,索引文件无重复排序存储。

非聚簇索引

将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,主文件并没有按照对应字段排序存储,索引文件有重复排序存储。

补充:

1.如果主文件的某一排序字段不是主码,则该字段上每个记录取值便不唯一,此时该字段被称为聚簇字段,聚簇索引通常是定义在聚簇字段上。
2.聚簇索引通常是对聚簇字段上每一个不同值有一个索引项。
3.一个主文件只能有一个聚簇索引文件,但可以有多个非聚簇索引文件。
4.主索引通常是聚簇索引,辅助索引通常是非聚簇索引。
5.主索引/聚簇索引是能够决定记录存储位置的索引,而非聚簇索引则只能用于查询,不能改变物理位置。

为什么主键通常建议使用自增id?

聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么可以想象,它会干些什么,不断地调整数据的物理地址、分页。

mysql中聚簇索引的设定?

聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键来作为聚簇索引。

什么是倒排索引和正排索引?
倒排索引

一个词汇包含在哪些文档中,倒排索引主要由两个部分组成:“单词词典”和“倒排文件”,应用于搜索引擎。

正排索引

一个文档包含了哪些词汇。

其他结构的索引?

1.多级索引:对索引再建立索引,如B书/B+树等;
2.多属性索引:索引字段由多个属性组合一起形成的索引;
3.散列索引:使用散列技术组织的索引;
4.网络索引:使用多索引字段进行交叉联合定位与检索;

进程 线程 协程

进程

资源的分配和调度的独立单元。进程拥有完整的虚拟地址空间,当发生进程切换时,不同的进程拥有不同的虚拟地址空间。而同一进程的多个线程是可以共享同一地址空间。

线程

CPU调度的基本单元,一个进程包含若干线程。
线程比进程小,基本上不拥有系统资源。线程的创建和销毁所需要的时间比进程小很多
由于线程之间能够共享地址空间,因此,需要考虑同步和互斥操作

线程和进程的区别

一个线程的意外终止会影响整个进程的正常运行,但是一个进程的意外终止不会影响其他的进程的运行。因此,多进程程序安全性更高。
总之,多进程程序安全性高,进程切换开销大,效率低;多线程程序维护成本高,线程切换开销小,效率高。

协程(Coroutine,又称微线程)

是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制。协程与线程以及进程的关系见下图所示。
在这里插入图片描述
1.协程可以比作子程序,但执行过程中,子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。协程之间的切换不需要涉及任何系统调用或任何阻塞调用
2.协程只在一个线程中执行,是子程序之间的切换,发生在用户态上。而且,线程的阻塞状态是由操作系统内核来完成,发生在内核态上,因此协程相比线程节省线程创建和切换的开销
3.协程中不存在同时写变量冲突,因此,也就不需要用来守卫关键区块的同步性原语,比如互斥锁、信号量等,并且不需要来自操作系统的支持。
协程适用于IO阻塞且需要大量并发的场景,当发生IO阻塞,由协程的调度器进行调度,通过将数据流yield掉,并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去运行。

如何选择

1.CPU密集型:多进程
2.IO密集型:多线程(协程维护成本较高,而且在读写文件方面效率没有显著提升)
3.CPU密集和IO密集:多进程+协程

Linux 进程通信

共享内存

在linux系统开发当中,存在多种方案可以实现进程之间的通信。但最高效的方法莫过于共享内存。但是共享内存传输的数据尽量不要太大。

共享内存原理

linux操作系统共享内存是借助tmpfs这个文件系统来实现的,tmpfs文件系的目录为/dev/shm,/dev/shm是驻留在内存 RAM 当中的,因此读写速度与读写内存速度一样,/dev/shm的容量默认尺寸为系统内存大小的一半大小,使用df -h命令可以看到。但实际上它并不会真正的占用这块内存,如果/dev/shm/下没有任何文件,它占用的内存实际上就是0字节,仅在使用shm_open文件时,/dev/shm才会真正占用内存。

Linux查看进程占用内存情况

查看进程占用内存大小的几种方法

1. pmap -x pid

2. ps -aux | grep 进程名

ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' | grep 进程名

3. top -d 1 -p pid

4. cat /proc/[pid]/status

多线程同步

为什么要同步

因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常。举个例子,如果一个银行账户同时被两个线程操作,一个取100块,一个存钱100块。假设账户原本有0块,如果取钱线程和存钱线程同时发生,会出现什么结果呢?取钱不成功,账户余额是100.取钱成功了,账户余额是0.那到底是哪个呢?很难说清楚。因此多线程同步就是要解决这个问题。

同步方式

同步方法

即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
** synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类。**

同步代码块

即有synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。
同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。

使用特殊域变量(volatile)实现线程同步

(1)volatile关键字为域变量的访问提供了一种免锁机制;
(2)使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新;
(3)因此每次使用该域就要重新计算,而不是使用寄存器中的值;
(4)volatile不会提供任何原子操作,它也不能用来修饰final类型的变量。
注:volatile不能保证原子操作导致的,因此volatile不能代替synchronized。此外volatile会组织编译器对代码优化,因此能不使用它就不使用它吧。它的原理是每次要线程要访问volatile修饰的变量时都是从内存中读取,而不是从缓存当中读取,因此每个线程访问到的变量值都是一样的。这样就保证了同步。

使用重入锁实现线程同步

在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和块具有相同的基本行为和语义,并且扩展了其能力。
ReenreantLock类的常用方法有:
ReentrantLock() :创建一个ReentrantLock实例
lock() :获得锁
unlock() :释放锁
注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用。
如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 。如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁。

使用局部变量实现线程同步

如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

ThreadLocal与同步机制

1.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题;
2.前者采用以”空间换时间”的方法,后者采用以”时间换空间”的方式。

Linux 异步信号

Linux swap分区

什么叫swap分区

即交换区,swap空间的作用可简单描述为:当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap中恢复保存的数据到内存中。

对性能的影响

Swap的调整对Linux服务器,特别是Web服务器的性能至关重要。通过调整Swap,有时可以越过系统性能瓶颈,节省系统升级费用。但是分配太多的Swap空间会浪费磁盘空间,而Swap空间太少,则系统会发生错误。

如果系统的物理内存用光了,系统就会跑得很慢,但仍能运行;如果Swap空间用光了,那么系统就会发生错误。例如,Web服务器能根据不同的请求数量衍生出多个服务进程(或线程)如果系统物理内存不够用,网站打开会很慢,ping可能会丢包,延迟很大;如果Swap空间用完,则服务进程无法启动,通常会出现“application is out of memory”的错误,严重时会造成服务进程的死锁。因此Swap空间的分配是很重要的。

划分规则

我们对swap分区的划分有一定的规则:
1.当物理内存小于2G时,swap分区大小为物理内存的2倍;超过2G的部分,swap分区大小跟物理内存相等。
2.当物理内存大于32G的时候,swap分区小于等于物理内存比较好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值