华为OD技术面真题 - 数据库MySQL - 3

文章目录

CHAR和VARCHAR的区别

CHAR 和 VARCHAR 是最常用到的字符串类型,两者的主要区别在于:CHAR 是定长字符串,VARCHAR 是变长字符串。

  • CHAR:存储时会在右边填充空格以达到指定的长度,检索时会去掉空格。CHAR 更适合存储长度较短或者长度都差不多的字符串
  • VARCHAR:存储时需要使用 1 或 2 个额外字节记录字符串的长度,检索时不需要处理。适合存储长度不确定或者差异较大的字符串.

CHAR(N) 和 VARCHAR(N) 的 N 都代表能够保存的字符数的最大值,无论是字母、数字还是中文,每个都只占用一个字符。

VARCHAR(100)和 VARCHAR(10)的区别是什么?

VARCHAR(100)VARCHAR(10) 的本质区别是:能存储的字符最大长度不同。VARCHAR 是变长存储,实际占用空间 = 真实字符长度 + 长度标记,虽然两个存储的字符数范围不同,但二者存储相同的字符串,所占用磁盘的存储空间其实是一样的。

在排序、临时表等执行阶段,MySQL 参考的是列的定义(DDL 中的长度) 来分配内部结构,而不会去统计或依赖实际数据中出现过的最大长度,更长的列会消耗更多的内存。所以在实际开发应该设置合适的长度。

DATETIME 和 TIMESTAMP 的区别是什么?如何选择?

核心区别对比:

维度 DATETIME TIMESTAMP
存储空间 8 字节 4 字节
是否受时区影响
取值范围 1000-01-01 ~ 9999-12-31 1970-01-01 ~ 2038-01-19
存储内容 字面时间 UTC 时间戳
是否自动更新 (需显式设置) (可配置)

使用场景:

DATETIME适用场景:

  • 需要存储大于2038年的时间
  • 不关注时区,不期望时区变化

TIMESTAMP适用场景:

  • 需要关注多时区时间转换。
  • 希望数据库能自动管理时区转换
  • 不超过TIMESTAMP存储范围。

表级锁和行锁的区别

  • 表级锁:MySQL 中锁定粒度比较大的一种锁,出现在针对非索引字段加的锁或存储引擎不支持行锁加锁的情况。对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。
  • 行级锁:MySQL 中锁定粒度最小的一种锁,是 针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的。MyISAM不支持行锁,InnoDB支持行锁。

共享锁和排他锁的区别

  • 共享锁:又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时对同一记录加共享锁。共享
  • 排他锁:又称互斥锁/写锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被当前加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)。排他

注意:一条记录已经被当前事务加了共享锁(S 锁),其他事务是不能再加排他锁(X 锁)的。

使用共享锁/排他锁示例

复制代码
# 共享锁
SELECT ... LOCK IN SHARE MODE;
# 排他锁
SELECT ... FOR UPDATE;

不同隔离级的加锁机制

  • 读未提交(Read Uncommitted): 采取的是读不加锁原理。事务读不加锁,不阻塞其他事务的读和写。事务写会加排它锁。
  • 读以提交(Read Committed): 相比读未提交,事务读中会加共享锁,但读取完成之后会立即释放锁。事务写会加排他锁。
  • 可重复读(REPEATABLE READ): 相比读已提交,事务读中会加共享锁,共享锁在事务结束之后进行释放。事务锁会加排他锁。
  • 串行化(SERIALIZABLE): 事务读会添加共享锁,事务写添加排他锁,对范围查询额外引入范围锁,防止幻读出现。

以上隔离级别和锁的关系只针对当前读,没有考虑快照读MVCC的影响。额外注意如果存储引擎不支持行锁/或者没走索引的情况,都会提升为表锁。

分别介绍一下当前读和快照读

当前读

定义:

  • 当前读就是直接读取数据库里"最新的实际数据",也就是数据页上的当前值。
  • 当前读可能会看到其他事务已提交的数据,也可能会被锁阻塞。
  • 读的时候可能会加锁(共享锁),写的时候加排他锁,保证事务隔离.

具体是否加锁与隔离级别有关。

特点:

  • 读取的是数据页实时的值。
  • 可能被锁阻塞或阻塞其他事务

快照读

定义:

  • 快照读就是读取某个事务启动时或语句开始时的数据版本快照,不会读取数据库中的最新实际值,而是读取版本数据。
  • 这种读不会加锁,也不会阻塞其他事务。

特点:

  • 读取的时候某个时间点数据的历史版本,与其它事务的修改无关。
  • 不加锁,不阻塞,也不会被阻塞。

介绍一下InnoDB中MVCC机制

MVCC中文名文多版本并发控制,通过维持一个数据的多个版本,通过不加锁方式,实现读写不阻塞,提高效率,并解决数据读取可见性问题。无锁。这是快照读的实现原理。

简单介绍一下MVCC实现原理,先介绍以下几个概念:

数据库中每行记录额外隐式定义了以下几个字段:

  • DB_ROW_ID1:隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引。
  • DB_TRX_ID: 最近修改/插入这条记录的四五ID。
  • DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本。
  • DELETED_BIT:记录被更新或删除的标志。

undoLog:数据库提供的回滚日志,在这里可以简单认为记录每行数据各个版本的日志文件,行数多个版本之间逻辑可认为存在一个双向链表连接,并且都存在一个特定标识,上面回滚指针指向其中一个链表节点。

快照读读取的读试图可以理解拥有以下三个属性:

  • trx_list: 未提交事务ID列表,用来维护Read View生成时刻系统正活跃的事务ID。
  • up_limit_id: 记录trx_list列表中事务ID最小的ID。
  • low_limit_id:ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1. 创建新事务时,会分配事务ID,并且全局递增

明白上面三个之后,MVCC处理读取可见性数据步骤为:

  • 事务开始时生成一个快照版本号。
  • 对于每一行数据的可见性:
    • 如果这行数据的trx_id == 当前事务id ,可以直接读取。
    • 如果这行数据的trx_id 小于快照中最小活跃事务,说明在这个事务开启之前,事务已经提交,可以直接读取。
    • 如果行的 trx_id 在快照活跃事务号范围内 → 不可见(其他事务未提交),通过记录的DB_ROLL_PTR和undolog回滚历史版本,找到第一个可见数据版本。

RC和RR隔离级别下MVCC的差异

事务隔离级别 RCRR (InnoDB 存储引擎的默认事务隔离级别)下,InnoDB 存储引擎使用 MVCC(非锁定一致性读),但它们生成 Read View 的时机却不同

  • 在 RC 隔离级别下的 每次select 查询前都生成一个Read View
  • 在 RR 隔离级别下只在事务开始后 第一次select 数据前生成一个Read View

由于生成读视图机制的不同,所以在 RC 隔离级别下会存在导致不可重复读问题。

相关推荐
heartbeat..2 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
Prince-Peng2 小时前
技术架构系列 - 详解Redis
数据结构·数据库·redis·分布式·缓存·中间件·架构
虾说羊2 小时前
redis中的哨兵机制
数据库·redis·缓存
_F_y3 小时前
MySQL视图
数据库·mysql
2301_790300963 小时前
Python单元测试(unittest)实战指南
jvm·数据库·python
九章-3 小时前
一库平替,融合致胜:国产数据库的“统型”范式革命
数据库·融合数据库
2401_838472513 小时前
使用Scikit-learn构建你的第一个机器学习模型
jvm·数据库·python
u0109272713 小时前
使用Python进行网络设备自动配置
jvm·数据库·python
wengqidaifeng4 小时前
数据结构---顺序表的奥秘(下)
c语言·数据结构·数据库