开课吧门徒计划必修基础课大厂工程师的必备算法能力

2021-03-04 07:29

阅读:494

1.关系型数据库: MySQL/Oracle/PostSQL

1.InnoDB引擎,事务处理机制

由于mysql中有两套日志机制,一套是存储层的redo log,另一套是server层的binlog,每次更新数据都要对两个日志进行更新。为了防止写日志时只写了其中一个而没有写另外一个,mysql使用了一个叫两阶段提交的方式保证事务的一致性

执行流程:

  1. 首先执行器会找引擎取ID=2这一行数据
  2. 拿到数据后会把数据进行+1操作,然后调用引擎接口把新数据写入
  3. 引擎将数据更新到内存中,并将操作记录到redo log里,此时redo log处于prepare状态。但它不会提交事务,只是通知执行器已经完成任务,可以随时提交。
  4. 执行器生成这个操作的binlog,并把binlog写入磁盘
  5. 最后执行器调用引擎的事务接口,把redo log改为提交状态,更新完成。

2.MySQL优化

粗说:

  1. 加索引的时候尽量准确,避免造成不必要的锁定影响其他查询。

  2. 尽量减少给予范围的数据检索(间隙锁),避免因为间隙锁带来的影响,锁定了不该锁定的记录。

  3. 尽量控制事务的大小,减少锁定的资源量和锁定时间。

  4. 尽量使用较低级别的事务隔离,减少 MySQL 因为事务隔离带来的成本。

细说:

  1. 频繁变动的字段, 不适合建索引
  2. 离散度越高越好, 离散低不适合建索引
  3. like "asd%" 都不一定用索引,其他位置都不用索引查询
  4. 比对规则从左往右, 离散高放前边, 一个索引器反复, 最左前缀原则
  5. 去掉冗余索引, 有联合索引, 就不要单个的联合索引的列
  6. 能用覆盖索引(主键), 就千万不要 select *, 速度至少快1倍
  7. 用or 索引会失效

3.MySQL锁相关

 
技术图片
image-20200420125031591.png

锁分类:

  • 表级锁:对整张表加锁。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

  • 行级锁:对某行记录加锁。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

  • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

 
技术图片
image-20200420131311713.png

表级锁:

意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前,必须先取得该表的 IS 锁。

意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前,必须先取得该表的 IX 锁。

注:意向共享锁和意向排他锁是数据库主动加的,不需要我们手动处理。对于 UPDATE、DELETE 和 INSERT 语句,InnoDB 会自动给数据集加排他锁。

行级锁:

共享锁(S):当一个事务读取一条记录的时候,不会阻塞其他事务对同一记录的读请求,但会阻塞对其的写请求。当读锁释放后,才会执行其他事务的写操作。

例如:select … lock in share mode

排他锁(X):当一个事务对一条记录进行写操作时,会阻塞其他事务对同一表的读写操作,当该锁释放后,才会执行其他事务的读写操作。

共享锁,排他锁,意向共享锁,意向排他锁兼容图例

如果一个事务请求的锁模式与当前的锁兼容, InnoDB 就将请求的锁授予该事务;反之, 如果两者不兼容,该事务就要等待锁释放。

 
技术图片
image-20200420131855568.png

间隙锁

前面谈到行锁是针对一条记录进行加锁。当对一个范围内的记录加锁的时候,我们称之为间隙锁。

当使用范围条件索引数据时,InnoDB 会对符合条件的数据索引项加锁。对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB 也会对这个“间隙”加锁,这就是间隙锁。间隙锁和行锁合称(Next-Key锁)。

死锁

两个事务都需要获得对方持有的排他锁才能继续完成任务,这种互相等待对方释放资源的情况就是死锁。

避免死锁:

  1. 第一步查询,第二步更新.查询时直接上排它锁
  2. 同时需要查询修改多个表,按同样的顺序进行加锁

MySQL 锁定情况的查询

在实际开发中无法避免数据被锁的问题,那么我们可以通过哪些手段来查询锁呢?

表级锁可以通过两个变量的查询:

Table_locks_immediate,产生表级锁的次数。

Table_locks_waited,数显表级锁而等待的次数。

行级锁可以通过下面几个变量查询:

Innodb_row_lock_current_waits,当前正在等待锁定的数量。

Innodb_row_lock_time(重要),从系统启动到现在锁定总时长。

Innodb_row_lock_time_avg(重要),每次等待所花平均时间。


评论


亲,登录后才可以留言!