💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 知识点3mysql 悲观锁-一锁二查三更新pcc,pessimistic concurrency control 乐观锁-在数据上加一个版本号或者时间戳occ,optimistic concurrency control acid: A: 原子性(atomicity) C: 一致性(consistency) I: 隔离行(isolation) D: 持久性(durability) MySQL事务的实现 隔离性通过Mysql InnoDB锁就可以实现, 原子性、一致性、持久性通过数据库的redo和undo来完成 对于事务操作的统计 QPS:question per second,每秒请求数 TPS:transaction per second,每秒事务处理的能力 计算TPS的方法是(com_commit+com_rollback)/time,用这种方法的前提是,所有的事务必须都是显式提交的。 SQL标准定义的四个隔离级别为: 1、READ UNCOMMITED 2、READ COMMITED 3、REPEATABLE READ 4、SERIALIZABLE 1, READ UNCOMMITTED(未提交读) 事务中的修改,即使没有提交,对其它事务也是可见的. 脏读(Dirty Read). 2, READ COMMITTED(提交读) 一个事务开始时,只能"看见"已经提交的事务所做的修改. 这个级别有时候也叫不可重复读(nonrepeatable read). 3, REPEATABLE READ(可重复读) 该级别保证了同一事务中多次读取到的同样记录的结果是一致的. 但理论上,该事务级别还是无法解决另外一个幻读的问题(Phantom Read). 幻读: 当某个事务读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录.当之前的事务再次读取该范围时,会产生幻行.(Phantom Row). 幻读的问题理应由更高的隔离级别来解决,但mysql和其它数据不一样,它同样在可重复读的隔离级别解决了这个问题. 也就是说, mysql的可重复读的隔离级别解决了 "不可重复读" 和 “幻读” 2个问题. 稍后我们可以看见它是如何解决的. 而oracle数据库,可能需要在 “SERIALIZABLE ” 事务隔离级别下才能解决 幻读问题. mysql默认的隔离级别也是: REPEATABLE READ(可重复读) 4, SERIALIZABLE (可串行化) 强制事务串行执行,避免了上面说到的 脏读,不可重复读,幻读 三个的问题. mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set mysql> select @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ 1 row in set mysql> show variables like 'innodb_support_xa'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | innodb_support_xa | ON | +-------------------+-------+ 1 row in set MVCC(Multi-Version Concurrency Control) 多版本并发控制 MVCC的实现,是通过保存数据在某个时间点的快照来实现的. InnoDB的MVCC是通过在每行记录后面保存2个隐藏的列来实现的,一列保存了行的创建时间,一列保存了行的过期时间(或删除时间).但它们都存储的是系统版本号 MVCC最大的作用是: 实现了非阻塞的读操作,写操作也只锁定了必要的行.(并行读,行锁) MYSQL的MVCC 只在 read committed 和 repeatable read 2个隔离级别下工作. InnoDB 锁的算法 5.1 Record Lock: 单个行记录的锁 5.2 GAP Lock: 间隙锁,锁定一个范围,但不包含记录本身. 5.3 Next-Key Lock: Gap Lock+Record Lock 锁定一个范围并锁定记录本身. 下面的2句话是InnoDB在不同隔离级别下产生"不可重复读" 和 "幻读" 和解决它 的根本原因: InnoDB存储引擎默认的事务隔离级别(repeatable read)下,采用的是 Next-Key Locking的方式来加锁. read committed隔离级别下采用的是: Record Lock 的方式来加锁. 总结: 1, InnoDB用MVCC来实现非阻塞的读操作,不同隔离级别下,MVCC通过读取不同版本的数据来解决"不可重复读" 的问题. 2, InnoDB的默认隔离级别解决2个问题,"不可重复读" 和 "幻读", oracle需要在串行读中解决"幻读"问题. InnoDB的实现方式和一般隔离级别的定义不一致. 3, InnoDB的默认隔离级别采用Next-key Lock(间隙锁) 来解决幻读问题. 而 read committed隔离级别采用Record锁,因此会产生"幻读"问题. 4, InnoDB的存储引擎不存在锁升级的问题(太多的行锁升级为表锁),来降低锁的开销. 因为不是根据记录来产生行锁的,根据页对锁进行管理. 事务的分类 1.1 扁平事务 要么都执行,要么都回滚,InnoDB最常用,最常见的事务. 1.2 带有保存点的偏平事务 事务的操作过程有 begin, A, B, C, D, commit 几个过程,那么带有保存点的扁平事务过程大致如下: begin--> 隐含保存点1(save work 1)-->A-->B(save work2)-->C-->D(rollback work2) -->commit 上述过程中如果遇到rollback work2, 只需要回滚到保存点2,不需要全部回滚. 简单来说,带有保存点的扁平事务就是有计划的回滚操作。 保存点是容易失的(volatile), 而非持久的.系统崩溃,所有保存点都将丢失. 1.3 链事务 链事务提交一个事务时,释放不需要的数据对象,将必要的上下文传递给下一个要开始的事务. 下一个事务可以看到上一个事务的结果. 带有保存点的偏平事务可以回滚到任意正确的保存点,链事务只能回滚到当前事务. 扁平全程持锁,链事务在commit后释放锁. 链事务如: T1->T2->T3 1.4 嵌套事务 可以理解为一颗事务树,顶层事务控制着下面的子事务. 所有的叶子节点是扁平事务,实际工作是由叶子节点完成的. 1.5 分布式事务 分布式环境下运行的扁平事务. InnoDB支持上述除嵌套事务以外的所有事务类型. 总结 1, redo log(事务日志)保证事务的原子性和持久性(物理日志) 2, undo log保证事务的一致性,InnoDB的MVCC也是用undo log来实现的(逻辑日志). 3, redo log中带有有checkPoint,用来高效的恢复数据. 4, 物理日志记录的是修改页的的详情,逻辑日志记录的是操作语句. 物理日志恢复的速度快于逻辑日志.