← 返回目录

2. 事务

第 164 / 230 卷日期:

  1. delete 语句的和查询的加锁方式相同
  2. limit 语句,遍历到满足条件的 n 条数据后,之后不再加 next-key lock

死锁:不同线程可以给同一个间隙加锁。

意思时只有我这个线程可以操控这个间隙,其他线程不能使用,加锁时不会检测是否冲突的,但是如果两个都给同一个间隙上锁,之后两个线程都没办法在这个间隙上更新数据了,都会陷入等待另一个线程的间隙锁释放,也就是

死锁。

如果使用读提交隔离级别,那么只加行锁,不加间隙锁,语句执行过程中加上的行锁,在语句执行完成后,就要把 “不满足条件的行”上的行锁直接释放了,不需要等到事务提交才释放。

2. 事务

2-1:for update的使用场景

一般这些操作都是很长一串并且是开启事务的。

如果库存刚开始读的时候是1,而立马另一个进程进行了update将库存更新为0了,而事务还没有结束,会将错的数据一直执行下去,就会有问题。

需要 for upate 进行数据加锁防止高并发时候数据出错,即使事务保持当前读状态。

SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset;

# 如果只给定一个参数,表示记录数。

mysql> SELECT * FROM orange LIMIT 5;# 检索前5条记录(1-5)

相当于

mysql> SELECT * from orange LIMIT 0,5;

两个参数,第一个参数表示offset, 第二个参数为记录数。

mysql> SELECT * FROM orange LIMIT 10,15; // 检索记录11-25

如果你想要清除一些MySQL使用内部缓存,你应该使用FLUSH命令

2-2:事务隔离

innodb 支持 RC 和 RR 隔离级别实现是用的一致性视图(consistent read view)

事务在启动时会拍一个快照,这个快照是基于整个库的。

基于整个库的意思就是说一个事务内,整个库的修改对于该事务都是不可见的(对于快照读的情况)

如果在事务内 select t 表,另外的事务执行了DDL t表,根据发生时间,只有两种情况

  1. 报错

(2)事务在启动时,找到已提交的最大事务ID记为up_limit_id。

(3)事务在更新一条语句时

比如 id=1 改为了 id=2.会把 id=1 和该行之前的 row trx_id 写到 undo log 里, 并且在数据页上把 id 的值改为 2,并且把修改这条语句的transaction id 记在该行行头

(4)再定一个规矩

一个事务要查看一条数据时,必须先用该事务的 up_limit_id 与该行的transaction id 做比对

如果 up_limit_id >= transaction id,那么可以看如果 up_limit_id < transaction id,则只能去 undo log 里去取。

去 undo log 查找数据的时候,也需要做比对,必须 up_limit_id > transaction id,才返回数据

2-3:什么是当前读

由于当前读都是先读后写,只能读当前的值,所以为当前读会更新事务内的 up_limit_id 为该事务的 transaction

你提到了隐藏列有一个DB_ROW_ID,是干嘛的?那假设有10个update,到第九个回滚了,DB_ROLL_PTR如何做的,那提交了是否更新DB_ROLL_PTR?

为什么 rr 能实现可重复读而 rc 不能,分两种情况

(1)快照读的情况下:

rr不能更新事务内的 up_limit_id ,而 rc 每次会把 up_limit_id 更新为快照读之前最新已提交事务的 transaction id, 则 rc 不能可重复读

(2)当前读的情况下:

rr 是利用 record lock+gap lock来实现的,而 rc 没有 gap,所以 rc 不能可重复读

2-4:选择普通索引还是唯一索引?

1、对于查询过程来说:

(1)普通索引

查到满足条件的第一个记录后,继续查找下一个记录,知道第一个不满足条件的记录

(2)唯一索引

由于索引唯一性,查到第一个满足条件的记录后,停止检索

但是,两者的性能差距微乎其微。因为InnoDB根据数据页来读写的。

2、对于更新过程来说:

概念:change buffer

当需要更新一个数据页:

purge:将 change buffer 中的操作应用到原数据页上,得到最新结果的过程,成为 purge

访问这个数据页会触发 purge,系统有后台线程定期 purge,在数据库正常关闭的过程中,也会执行 purge

唯一索引的更新不能使用 change buffer

change buffer 用的是 buffer pool 里的内存,change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为50的时候,表示 change buffer 的大小最多只能

占用 buffer pool 的50%。

将数据从磁盘读入内存涉及随机IO的访问,是数据库里面成本最高的操作之一。

change buffer 因为减少了随机磁盘访问,所以对更新性能的提升很明显。

change buffer使用场景:

在一个数据页做purge之前,change buffer记录的变更越多,收益就越大。

对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时change buffer的使用效果最好。这种业务模型常见的就是账单类、日志类的系统。

反过来,假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件,将更新先记录在change buffer,但之后由于马上要访问这个数据页,会立即触发purge过程。

这样随机访问IO的次数不会减少,反而增加了change buffer的维护代价。所以,对于这种业务模式来说,change buffer反而起到了副作用。

索引的选择和实践:

尽可能使用普通索引。

redo log主要节省的是随机写磁盘的IO消耗(转成顺序写),而change buffer主要节省的则是随机读磁盘的IO消耗。

2-5:char 和 varchar 的区别?

char 是固定长度类型,比如:定义 char(10),当你输入”abc”三个字符的时候,它们占的空间还是 10 个字节,其他 7 个是空字节。varchar 长度可变

存储情况不同

以 compact 行格式为例:

一条完整的记录由两部分组成

  1. 变长字段的真正数据内容
  2. 该变长字段所占用的字节数

该变长字段所占用的字节数被放在变长字段列表中,并且按照列的顺序逆序存放。

而 char 类型的数据则只需要存储其真正的数据内容。

对于类型为 char(M) 的列

全站分卷索引 · 230 卷
  1. 1代码随想录知识星球精华(最强八股文)第五版(计算机基础篇)
  2. 2DNS
  3. 3DNS解析过程
  4. 4递归查询和迭代查询
  5. 5HTTP特性与简述
  6. 6HTTP版本演变
  7. 7HTTP/2
  8. 8HTTP1.1协议的性能问题
  9. 9兼容HTTP1.1
  10. 10二进制帧
  11. 11并发传输
  12. 12服务器主动推送资源
  13. 13总结
  14. 14HTTP/3
  15. 15HTTP/2的缺点
  16. 16QUIC协议的特点
  17. 17HTTP/3协议
  18. 18HTTP缓存
  19. 19协商缓存
  20. 20HTTPS
  21. 21HTTPS的特点
  22. 22非对称加密
  23. 23摘要算法+数字签名
  24. 24数字证书
  25. 25证书信任链
  26. 26HTTPS是怎么建立连接的
  27. 27TCP与UDP头部格式
  28. 28TCP
  29. 29列举TCP选项
  30. 30TCP三次握手
  31. 31为什么需要三次握手?
  32. 32什么是半连接队列
  33. 33什么是SYN攻击
  34. 34为什么挥手需要四次
  35. 35TIME_WAIT 过多有什么危害?
  36. 36TCP的滑动窗口
  37. 374. 程序是如何表示发送方的四个部分的呢?
  38. 386. 接收窗口和发送窗口的大小是相等的吗?
  39. 391. 慢启动
  40. 403. 拥塞发生
  41. 414. 快速恢复
  42. 42IP基础
  43. 43IP地址
  44. 44在浏览器中输入URL并按下回车之后会发生什么
  45. 45TCP 抓包实践
  46. 46TCP连接与断开优化
  47. 47TCP内核参数
  48. 48主动方的优化
  49. 49被动方的优化
  50. 50Linux是如何收发网络包的
  51. 51收发流程
  52. 52面试题
  53. 53TCP/IP四层网络模型
  54. 54五层网络体系结构
  55. 55HTTP响应报文
  56. 56HTTP常见字段
  57. 57什么是TCP粘包问题?如何解决TCP粘包问题?
  58. 58UDP会不会产生粘包问题呢?
  59. 59请求报文
  60. 60时间消耗
  61. 61HTTP缓存有几种
  62. 62HTTP1.0和HTTP1.1的区别?
  63. 63HTPP1.1和HTTP1.0有什么区别
  64. 64HTTP/3
  65. 65HTTPS是如何建立连接的
  66. 66DNS是什么
  67. 67递归查询和迭代查询
  68. 68TCP与UDP的区别
  69. 69TCP和UDP分别在什么场景使用?
  70. 70三次握手的过程
  71. 71Keep-Alive的优缺点
  72. 72CDN的工作流程
  73. 73Session的工作原理
  74. 74TCP重传机制是怎么实现的?
  75. 75什么是SS0
  76. 76HTTP优化方案
  77. 77浏览器地址栏输入URL回车后涉及到的流程
  78. 781.5 浏览器发送HTTP/HTTPS请求到web服务器
  79. 79SYN攻击
  80. 80操作系统
  81. 81操作系统的功能
  82. 82进程和线程
  83. 83线程基础
  84. 84进程调度
  85. 85进程调度方式
  86. 86进程通信
  87. 87消息传递(消息队列)
  88. 88信号量
  89. 89信号
  90. 90线程通信
  91. 91多线程
  92. 92进程通信
  93. 93消息队列
  94. 94信号
  95. 95守护进程
  96. 96互斥与同步
  97. 974. 互斥锁解锁
  98. 983. 处理方法
  99. 99读写锁
  100. 1002. 销毁读写锁
  101. 1014. 写锁定
  102. 1021. 创建条件变量
  103. 1034. 阻塞线程
  104. 104信号量
  105. 1054. V操作
  106. 1062. 读者-写者问题
  107. 107存储系统
  108. 108虚拟内存
  109. 109内存分段
  110. 110内存分页
  111. 111虚拟内存
  112. 112文件系统
  113. 1135. 文件访问
  114. 114目录
  115. 1154. 目录操作
  116. 1163. 目录的实现
  117. 1177. 虚拟文件系统
  118. 1184. 文件系统性能
  119. 119磁盘编址
  120. 120三层抽象
  121. 121外设管理
  122. 122Linux
  123. 123select/poll/epoll的区别和联系
  124. 124Linux 内存管理
  125. 125Linux虚拟内存
  126. 126Linux 信号
  127. 127Linux设计
  128. 1283. 各种IO模型的比较
  129. 129Linux网络
  130. 130Linux中的软链接和硬链接有什么区别?
  131. 131什么是中断和异常
  132. 132信号和信号量有什么区别
  133. 133Linux中如何查看一个进程
  134. 134进程、线程的区别?
  135. 135进程之间的通信方式
  136. 136如何解除死锁
  137. 137分段和分页的区别
  138. 138IO多路复用
  139. 139MySQL表连接
  140. 140过滤条件
  141. 141执行一次update语句,发生了什么
  142. 142用户账号存储
  143. 143用户账号删除
  144. 144索引
  145. 145索引有哪些类别
  146. 1462. 按照存储分类
  147. 1475. 按照字段个数分类
  148. 148索引区分度
  149. 149索引什么时候会失效
  150. 150事务的四大特性ACID
  151. 151并行事务会出现什么问题
  152. 152幻读是如何解决的
  153. 153事务隔离的实现
  154. 154读已提交是怎么实现的
  155. 155锁
  156. 1561、全局锁
  157. 1573、行级锁
  158. 158锁的划分
  159. 1592.、程序员角度
  160. 160Innodb使用表锁还是行锁
  161. 161什么是binlog
  162. 162执行引擎
  163. 163MySQL常见问题
  164. 1642. 事务
  165. 1653. 脏页
  166. 1664. 表结构
  167. 1676. 查询效率
  168. 168MySQL分库分表
  169. 169垂直分表
  170. 170水平分库
  171. 171分库分表的问题
  172. 172数据库排序思路
  173. 173MySQL主从复制
  174. 1745. 主从复制模式
  175. 175面试题
  176. 176执行一条select语句,发生了什么?
  177. 177你对关系范式有哪些了解
  178. 178数据库
  179. 179Redis基础
  180. 180Redis单线程为什么还这么快
  181. 181Redis底层数据结构
  182. 182Redis持久化
  183. 183AOF日志
  184. 184RDB快照
  185. 185Redis功能
  186. 1862. 哨兵模式
  187. 1873. 切片集群
  188. 188Redis哨兵机制是什么
  189. 189什么是集群脑裂
  190. 190过期删除策略有哪些
  191. 191Redis的LRU算法和LFU算法有什么区别
  192. 192什么是缓存击穿
  193. 193如何保证删除缓存操作一定能成功?
  194. 194为什么Redis是单线程
  195. 195Redis底层使用了什么数据结构
  196. 196Redis实现分布式锁
  197. 197缓存中的热点数据和冷数据是什么
  198. 198缓存雪崩、击穿、穿透和解决办法【常问】
  199. 199Redis过期删除策略有哪些
  200. 200关键概念
  201. 201单例模式的应用场景
  202. 202工厂模式
  203. 203实际应用
  204. 204抽象工厂模式
  205. 205概念
  206. 206应用
  207. 207实现步骤
  208. 208主要角色
  209. 209代理模式应用
  210. 210策略模式
  211. 211示例
  212. 212装饰模式
  213. 213主要角色
  214. 21423种设计模式的概念
  215. 215创建型模式
  216. 216行为型模式
  217. 217设计原则
  218. 218迪米特法则
  219. 219你在实际开发中用过哪些设计模式
  220. 220依赖倒置
  221. 221代理模式和适配器模式有什么区别
  222. 222固定长度编码
  223. 223冯诺依曼模型
  224. 224总线
  225. 225输入/输出设备
  226. 226编译系统如何工作
  227. 227处理器解释指令
  228. 228场景题 & 系统设计
  229. 229如何设计一个本地缓存
  230. 230如何设计一个RPC框架