python面试学习路线-5.数据库

5.数据库

要求: 能熟练使用、部署、调优、问题排查、懂原理

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(重要),每次等待所花平均时间。

Innodb_row_lock_time_max,从系统启动到现在等待最长的一次花费时间。

Innodb_row_lock_waits(重要),从系统启动到现在总共等待的次数。

特别注意,行锁使用不当会造成排它锁:

原文链接:https://blog.csdn.net/claram/java/article/details/54023216

1、只根据主键进行查询,并且查询到数据,主键字段产生行锁。

begin;
select * from goods where id = 1 for update;
commit;
2、只根据主键进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where id = 1 for update;
commit;
3、根据主键、非主键含索引(name)进行查询,并且查询到数据,主键字段产生行锁,name字段产生行锁。

begin;
select * from goods where id = 1 and name='prod11' for update;
commit;

4、根据主键、非主键含索引(name)进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where id = 1 and name='prod12' for update;
commit;
5、根据主键、非主键不含索引(name)进行查询,并且查询到数据,如果其他线程按主键字段进行再次查询,则主键字段产生行锁,如果其他线程按非主键不含索引字段进行查询,则非主键不含索引字段产生表锁,如果其他线程按非主键含索引字段进行查询,则非主键含索引字段产生行锁,如果索引值是枚举类型,mysql也会进行表锁,这段话有点拗口,大家仔细理解一下。

begin;
select * from goods where id = 1 and name='prod11' for update;
commit;
6、根据主键、非主键不含索引(name)进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where id = 1 and name='prod12' for update;
commit;
7、根据非主键含索引(name)进行查询,并且查询到数据,name字段产生行锁。

begin;
select * from goods where name='prod11' for update;
commit;
8、根据非主键含索引(name)进行查询,没有查询到数据,不产生锁。

begin;
select * from goods where name='prod11' for update;
commit;
9、根据非主键不含索引(name)进行查询,并且查询到数据,name字段产生表锁。

begin;
select * from goods where name='prod11' for update;
commit;
10、根据非主键不含索引(name)进行查询,没有查询到数据,name字段产生表锁。

begin;
select * from goods where name='prod11' for update;
commit;
11、只根据主键进行查询,查询条件为不等于,并且查询到数据,主键字段产生表锁。

begin;
select * from goods where id <> 1 for update;
commit;
12、只根据主键进行查询,查询条件为不等于,没有查询到数据,主键字段产生表锁。

begin;
select * from goods where id <> 1 for update;
commit;
13、只根据主键进行查询,查询条件为 like,并且查询到数据,主键字段产生表锁。

begin;
select * from goods where id like '1' for update;
commit;
14、只根据主键进行查询,查询条件为 like,没有查询到数据,主键字段产生表锁。

begin;
select * from goods where id like '1' for update;
commit;

乐观锁、悲观锁

  • 悲观锁方案:每次获取商品时,对该商品加排他锁。也就是在用户A获取获取 id=1 的商品信息时对该行记录加锁,期间其他用户阻塞等待访问该记录。悲观锁适合写入频繁的场景。

  • 乐观锁方案:每次获取商品时,不对该商品加锁。在更新数据的时候需要比较程序中的库存量与数据库中的库存量是否相等,如果相等则进行更新,反之程序重新获取库存量,再次进行比较,直到两个库存量的数值相等才进行数据更新。乐观锁适合读取频繁的场景

商城浏览商品下单这种高并发场景下,一般采用读写分离、异构数据库结构,读从Redis等缓存库里读,并发下单操作,锁机制可以用lua脚本、Redisson、zookpeer等方式做分布式锁、或者MySQL的排它锁,同时要防止死锁

事务隔离级别

读未提交(read uncommitted):它是最低的事务隔离级别,一个事务还没提交时,它做的变更就能被别的事务看到。有脏读的可能性。

读提交(read committed):保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。可避免脏读的发生,但是可能会造成不可重复读。

可重复读(repeatable read MySQL 默认方式):多次读取同一范围的数据会返回第一次查询的快照,即使其他事务对该数据做了更新修改。事务在执行期间看到的数据前后必须是一致的。即:事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容.

串行化(serializable):是最可靠的事务隔离级别。“写”会加“排他锁”,“读”会加“共享锁”。

2.NoSQL数据库: MongoDB/Elasticsearch(redis、hbase)

3.熟悉一些NewSQL数据库

4.海量数据库存储解决方案及原理

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 基础知识: 1.数据库的连接mysql -u -p -h-u 用户名-p 密码-h host主机 2:库级知识2....
    网络安全自修室阅读 1,452评论 0 1
  • 作者:我没有三颗心脏链接:https://www.jianshu.com/p/71927a377dc6来源:简书 ...
    GoldenCrow阅读 483评论 0 0
  • 数据库的基本是概念名词解释: 数据库名词解释 元组:可以理解为表的每一行就是一个元组 候选码:若关系中的某一属性组...
    杰伦哎呦哎呦阅读 1,099评论 0 6
  • 数据库优化 sql语句优化 索引优化 加缓存 读写分离 分区 分布式数据库(垂直切分) 水平切分 MyISAM和I...
    半瓶阳光o_o阅读 572评论 0 2
  • 老同学见面,除了吹捧、炫耀,互相扯皮,当初那种纯洁的同学氛围已经荡然无存。 虽未饮一滴酒,但人已似醉。 醉眼朦胧,...
    萧灿同學阅读 335评论 0 3