您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

彻底把 MySQL的锁搞懂了

时间:2023-02-06 13:52:24  来源:微信公众号  作者:猿java

基于读者反馈 肝了一周,这下彻底把 MySQL的锁搞懂了 排版有些不太清晰,特整理了一个新排版:

申明:本文基于 MySQL 8.0.30 版本,InnoDB 引擎

MySQL 数据库锁设计的初衷是处理并发问题,保证数据安全。MySQL 数据库锁可以从下面 3 个维度进行划分:

  1. 按照锁的使用方式,MySQL 锁可以分成共享锁、排他锁两种;

  2. 根据加锁的范围,MySQL 锁大致可以分成全局锁、表级锁和行锁三类;

  3. 从思想层面上看,MySQL 锁可以分为悲观锁、乐观锁两种;

     

我们先讲解共享锁和排它锁,然后讲解全局锁、表级锁和行锁,因为这三种类别的锁中,有些是共享锁,有些是排他锁,最后再讲解悲观锁和乐观锁。

图片

 

一、共享锁和排他锁

1.1 共享锁

共享锁,Share lock,也叫读锁。它是指当对象被锁定时,允许其它事务读取该对象,也允许其它事务从该对象上再次获取共享锁,但不能对该对象进行写入。加锁方式有如下两种方式:

#方式1select ... lock in share mode;#方式2select ... for share;

 

如果事务 T1 在某对象持有共享(S)锁,则事务 T2 需要再次获取该对象的锁时,会出现下面两种情况:

  1. 如果 T2 获取该对象的共享(S)锁,则可以立即获取锁;

  2. 如果 T2 获取该对象的排他(X)锁,则无法获取锁;

     

为了更好的理解上述两种情况,可以参照下面的执行顺序流和实例图:

给 user 表加共享锁

加锁线程 sessionA 线程 B sessionB
#开启事务
begin;
 
#对 user 整张表加共享锁
select * from user lock in share mode;
 
  #获取 user 表上的共享锁 ok,select 操作成功执行
select * from user;
  #获取 user 表上的排他锁失败,操作被堵塞
delete from user where id = 1;
#提交事务
#user 表上的共享锁被释放
commit;
 
  #获取 user 表上的排他锁成功,delete 操作执行 ok
delete from user where id = 1;

图片

 

给 user 表 id=3 的行加共享锁

加锁线程 sessionA 线程 B sessionB 线程 C sessionC
#开启事务begin;    
#给 user 表 id=3 的行加共享锁select * from userwhere id = 3 lock in share mode;    
  #获取 user 表 id=3 行上的共享锁 ok#select 操作执行成功select * from user where id=3; #获取 user 表 id=3 行上的共享锁 ok#select 操作执行成功select * from user where id=3;
  #获取 user 表 id=3 行上的排它锁失败#delete 操作被堵塞delete from user where id = 3; #获取 user 表 id=4 行上的排它锁成功#delete 操作执行成功delete from user where id = 4;
#提交事务#user 表 id=3 的行上共享锁被释放commit;    
  #获取 user 表 id=3 行上的排它锁成功#被堵塞的 delete 操作执行 okdelete from user where id = 3;  

图片

通过上述两个实例可以看出:

  • 当共享锁加在 user 表上,则其它事务可以再次获取 user 表的共享锁,其它事务再次获取 user 表的排他锁失败,操作被堵塞;

  • 当共享锁加在 user 表 id=3 的行上,则其它事务可以再次获取 user 表 id=3 行上的共享锁,其它事务再次获取 user 表 id=3 行上的排他锁失败,操作被堵塞,但是事务可以再次获取 user 表 id!=3 行上的排他锁;

 

1.2 排他锁

排它锁,Exclusive Lock,也叫写锁或者独占锁,主要是防止其它事务和当前加锁事务锁定同一对象。同一对象主要有两层含义:

  1. 当排他锁加在表上,则其它事务无法对该表进行 insert,update,delete,alter,drop 等更新操作;

  2. 当排他锁加在表的行上,则其它事务无法对该行进行 insert,update,delete,alter,drop 等更新操作;

     

排它锁加锁方式为:

​​​​​​# 排它锁加锁方式select ... for update;

 

为了更好地说明排他锁,可以参照下面的执行顺序流和实例图:

给 user 表对象加排他锁

加锁线程 sessionA 线程 B sessionB
#开启事务 begin;  
#对 user 整张表加排他锁
select * from user for update;
 
  #获取 user 表上的共享锁 ok,select 执行成功
select * from user;
  #获取 user 表上的排他锁失败,操作被堵塞
delete from user where id=3;
#提交事务
#user 表上的排他被释放
commit;
 
  #获取 user 表上的排他锁成功,操作执行 ok
delete from user where id = 1;

图片

给 user 表 id=3 的行对象加排他锁

加锁线程 sessionA 线程 B sessionB 线程 C sessionC
#开启事务
begin;
   
#给 user 表 id=3 的行加排他锁
select * from user
where id = 3 for update;
   
  #获取 user 表 id=3 行上的共享锁 ok
select * from user where id=3;
#获取 user 表 id=3 行上的共享锁 ok
select * from user where id=3;
  #获取user表id=3 行上的排它锁失败
delete from user where id = 3;
#获取 user 表 id=4 行上的排它锁成功
delete from user where id = 4;
#提交事务
#user 表 id=3 的行上排他锁被释放
commit;
   
  #获取 user 表 id=3 行上的排它锁成功
#被堵塞的 delete 操作执行 ok
delete from user where id = 3;
 

图片

 

二、全局锁 & 表锁 & 行锁

2.1 全局锁

全局锁,顾名思义,就是对整个数据库实例加锁,它是粒度最大的锁。

在 MySQL 中,通过执行 flush tables with read lock 指令加全局锁:

​​​​​​# 加全局锁flush tables with read lock

 

指令执行完,整个数据库就处于只读状态了,其他线程执行以下操作,都会被阻塞:

  • 数据更新语句被阻塞,包括 insert, update, delete 语句;

  • 数据定义语句被阻塞,包括建表 create table,alter table、drop table 语句;

  • 更新操作事务 commit 语句被阻塞;

 

MySQl 释放锁有 2 种方式:

  1. 执行 unlock tables 指令:unlock tables

  2. 加锁的会话断开,全局锁也会被自动释放

 

为了更好地说明全局锁,可以参照下面的执行顺序流和实例图:

加锁线程 sessionA 线程 B sessionB
flush tables with read lock; 加全局锁  
select user 表 ok select user 表 ok
insert user 表堵塞 insert user 表堵塞
delete user 表堵塞 delete user 表堵塞
drop user 表堵塞 drop user 表堵塞
alter user 表 堵塞 alter user 表 堵塞
unlock tables;解锁  
被堵塞的修改操作执行 ok 被堵塞的修改操作执行 ok

图片

通过上述的实例可以看出,当加全局锁时,库下面所有的表都处于只读状态,不管是当前事务还是其他事务,对于库下面所有的表只能读,不能执行 insert,update,delete,alter,drop 等更新操作。

全局锁的典型使用场景是做全库逻辑备份,在备份过程中整个库完全处于只读状态。如下图:

图片

假如在主库上备份,备份期间,业务服务器不能对数据库执行更新操作,因此涉及到更新操作的业务就瘫痪了;

假如在从库上备份,备份期间,从库不能执行主库同步过来的 binlog,会导致主从延迟越来越大,如果做了读写分离,那么从库上获取数据就会出现延时,影响业务;

从上述分析可以看出,使用全局锁进行数据备份,不管是在主库还是在从库上进行备份操作,对业务总是不太友好。那不加锁行不行?我们可以通过下面还钱转账的例子,看看不加锁会不会出现问题:

图片

  • 备份前:账户 A 有 1000,账户 B 有 500

  • 此时,发起逻辑备份

  • 假如数据备份时不加锁,此时,客户端 A 发起一个还钱转账的操作:账户 A 往账户 B 转 200

  • 当账户 A 转出 200 完成,账户 B 转入 200 还未完成时,整个数据备份完成

  • 如果用该备份数据做恢复,会发现账户 A 转出了 200,账户 B 却没有对应的转入记录,这样就会产生纠纷:A 说我账户少了 200, B 说我没有收到,最后,A,B 谁都不干。

既然不加锁会产生错误,加全局锁又会影响业务,那么有没有两全其美的方式呢?

有,MySQL 官方自带的逻辑备份工具 mysqldump,具体指令如下:

​​​​​​# 备份数据mysqldump –single-transaction

执行该指令,在备份数据之前会先启动一个事务,来确保拿到一致性视图, 加上 MVCC 的支持,保证备份过程中数据是可以正常更新。但是,single-transaction 方法只适用于库中所有表都使用了事务引擎,如果有表使用了不支持事务的引擎,备份就只能用 FTWRL 方法。

2.2 表级锁   

MySQL 表级锁有两种:

  1. 表锁

  2. 元数据锁(metadata lock,MDL)

 

2.2.1 表锁

表锁就是对整张表加锁,包含读锁和写锁,由 MySQL Server 实现,表锁需要显示加锁或释放锁,具体指令如下:

#给表加写锁lock tables tablename write;
# 给表加读锁lock tables tablename read;
# 释放锁unlock tables;

 

读锁代表当前表为只读状态,读锁是一种共享锁。需要注意的是,读锁除了会限制其它线程的操作外,也会限制加锁线程的行为,具体限制如下:

  • 加锁线程只能对当前表进行读操作,不能对当前表进行更新操作,不能对其它表进行所有操作;

  • 其它线程只能对当前表进行读操作,不能对当前表进行更新操作,可以对其它表进行所有操作;

 

为了更好地说明读锁,可以参照下面的执行顺序流和实例图:

加锁线程 sessionA 线程 B sessionB
#给 user 表加读锁
lock tables user read;
 
select user 表 ok select user 表 ok
insert user 表被拒绝 insert user 表堵塞
insert address 表被拒绝 insert address 表 ok
select address 表被拒绝 alter user 表堵塞
unlock tables; 释放锁  
  被堵塞的修改操作执行 ok

图片

写锁:写锁是一种独占锁,需要注意的是,写锁除了会限制其它线程的操作外,也会限制加锁线程的行为,具体限制如下:

  • 加锁线程对当前表能进行所有操作,不能对其它表进行任何操作;

  • 其它线程不能对当前表进行任何操作,可以对其它表进行任何操作;

     

为了更好的说明写锁,可以参照下面的执行顺序流和实例图:

加锁线程 sessionA 线程 B sessionB
#给 user 表加写锁
lock tables user write;
 
select user 表 ok select user 表 ok
insert user 表被拒绝 insert user 表堵塞
insert address 表被拒绝 insert address 表 ok
select address 表被拒绝 alter user 表堵塞
unlock tables; 释放锁  
  堵塞在 user 表的上更新操作执行 ok

图片

 

2.2.2 MDL 元数据锁   

元数据锁:metadata lock,简称 MDL,它是在 MySQL 5.5 版本引进的。元数据锁不用像表锁那样显式的加锁和释放锁,而是在访问表时被自动加上,以保证读写的正确性。加锁和释放锁规则如下:

  • MDL 读锁之间不互斥,也就是说,允许多个线程同时对加了 MDL 读锁的表进行 CRUD(增删改查)操作;

  • MDL 写锁,它和读锁、写锁都是互斥的,目的是用来保证变更表结构操作的安全性。也就是说,当对表结构进行变更时,会被默认加 MDL 写锁,因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

  • MDL 读写锁是在事务 commit 之后才会被释放;

     

为了更好的说明 MDL 读锁规则,可以参照下面的顺序执行流和实例图:

加锁线程 sessionA 其它线程 sessionB
开启事务
begin;
 
select user 表,user 表会默认加上 MDL 读锁  
select user 表 ok select user 表 ok
insert user 表 ok insert user 表 ok
update user 表 ok update user 表 ok
delete user 表 ok delete user 表 ok
  alter user 表,获取 MDL 写锁失败,操作被堵塞
commit;提交事务,MDL 读锁被释放  
  被堵塞的修改操作执行 ok

图片

为了更好的说明 MDL 写锁规则,可以参照下面的顺序执行流和实例图:

加锁线程 sessionA 线程 B sessionB 线程 C sessionC
#开启事务
begin;
   
#user 表会默认加上 MDL 读锁
select user 表,
   
select user 表 ok select user 表 ok select user 表 ok
  #获取 MDL 写锁失败
alter user 表操作被堵塞
#获取 MDL 读锁失败
select * from user;
提交事务,MDL 读锁被释放    
  #MDL 写锁被释放
被堵塞的 alter user 操作执行 ok
 
    #被堵塞的 select 操作执行 ok

图片

 

2.2.3 意向锁

由于 InnoDB 引擎支持多粒度锁定,允许行锁和表锁共存,为了快速的判断表中是否存在行锁,InnoDB 推出了意向锁。

意向锁,Intention lock,它是一种表锁,用来标识事务打算在表中的行上获取什么类型的锁。不同的事务可以在同一张表上获取不同种类的意向锁,但是第一个获取表上意向排他(IX) 锁的事务会阻止其它事务获取该表上的任何 S 锁 或 X 锁。反之,第一个获得表上意向共享锁(IS) 的事务可防止其它事务获取该表上的任何 X 锁。

意向锁通常有两种类型:

  1. 意向共享锁(IS),表示事务打算在表中的各个行上设置共享锁。

  2. 意向排他锁(IX),表示事务打算对表中的各个行设置排他锁。


意向锁是 InnoDB 自动加上的,加锁时遵从下面两个协议:

  1. 事务在获取表中行的共享锁之前,必须先获取表上的 IS 锁或更强的锁。

  2. 事务在获取表中行的排他锁之前,必须先获取表上的 IX 锁。

     

为了更好地说明意向共享锁,可以参照下面的顺序执行流和实例图:

加锁线程 sessionA 线程 B sessionB
#开启事务
begin;
 
#user 表 id=6 加共享行锁 ,默认 user 表会 加上 IS 锁
select * from user where id = 6 for share;
 
  # 观察 IS 锁
select* from performance_schema.data_locksG

图片

加锁线程 sessionA 线程 B sessionB
#开启事务
begin;
 
#user 表 id=6 加排他锁,默认 user 表会 加上 IX 锁
select * from user where id = 6 for update;
 
  # 观察 IX 锁
select* from performance_schema.data_locksG

图片

 

2.2.4 AUTO-INC 锁

AUTO-INC 锁是一种特殊的表级锁,当表中有 AUTO_INCREMENT 的列时,如果向这张表插入数据时,InnoDB 会先获取这张表的 AUTO-INC 锁,等插入语句执行完成后,AUTO-INC 锁会被释放。

AUTO-INC 锁可以使用 innodb_autoinc_lock_mode 变量来配置自增锁的算法,innodb_autoinc_lock_mode 变量可以选择三种值如下表:

innodb_autoinc_lock_mode 含义
0 传统锁模式,采用 AUTO-INC 锁
1 连续锁模式,采用轻量级锁
2 交错锁模式(MySQL8 默认),AUTO-INC 和轻量级锁之间灵活切换

为了更好的说明 AUTO-INC 锁,可以参照下面的顺序执行流和实例图:

 

表级锁的兼容性 

下面的图表总结了表级锁类型的兼容性

  X IX S IS
X 冲突 冲突 冲突 冲突
IX 冲突 兼容 冲突 兼容
S 冲突 冲突 兼容 兼容
IS 冲突 兼容 兼容 兼容

 

2.3 行锁   

行锁是针对数据表中行记录的锁。MySQL 的行锁是在引擎层实现的,并不是所有的引擎都支持行锁,比如,InnoDB 引擎支持行锁而 MyISAM 引擎不支持。

InnoDB 引擎的行锁主要有四类:

  1. Record Lock:记录锁,是在索引记录上加锁;

  2. Gap Lock:间隙锁,锁定一个范围,但不包含记录;

  3. Next-key Lock:Gap Lock + Record Lock,锁定一个范围(Gap Lock 实现),并且锁定记录本身(Record Lock 实现);

  4. 插入意向锁;

 

2.3.1 Record Lock

Record Lock:记录锁,是针对索引记录的锁,锁定的总是索引记录。

例如,select id from user where id = 1 for update; for update 就显式在索引 id 上加行锁(排他锁),防止其它任何事务 update 或 delete id=1 的行,但是对 user 表的 insert、alter、drop 操作还是可以正常执行。

为了更好的说明 Record Lock 锁,可以参照下面的执行顺序流和实例图:

加锁线程 sessionA 线程 B sessionB 线程 B sessionC
#开启事务
begin;
   
给 user 表 id=1 加写锁
select id from user
where id = 1 for update;
   
  update user set name = 'name121'
where id = 1;
 
    #查看 InnoDB 监视器中记录锁数据
show engine innodb statusG
commit 提交事务
record lock 被释放
   
  被堵塞的 update 操作执行 ok  

图片

 

2.3.2 Gap Lock 

Gap Lock:间隙锁,锁住两个索引记录之间的间隙上,由 InnoDB 隐式添加。比如(1,3) 表示锁住记录 1 和记录 3 之间的间隙,这样记录 2 就无法插入,间隙可能跨越单个索引值、多个索引值,甚至是空。

图片

为了更好的说明 Gap Lock 间隙锁,可以参照下面的顺序执行流和实例图:

加锁线程 sessionA 线程 B sessionB 线程 C sessionC
#开启事务
begin;
   
加锁
select * from user
where age = 10 for share;
   
  insert into user(id,age) values(2,20);  
    #查看 InnoDB 监视器中记录锁数据
show engine innodb statusG
commit 提交事务
Gap Lock 被释放
   
  被堵塞的 insert 操作执行 ok  

图片

上图中,事务 A(sessionA)在加共享锁的时候产生了间隙锁(Gap Lock),事务 B(sessionB)对间隙中进行 insert/update 操作,需要先获取排他锁(X),导致阻塞。事务 C(sessionC)通过"show engine innodb statusG" 指令可以查看到间隙锁的存在。需要说明的,间隙锁只是锁住间隙内部的范围,在间隙外的 insert/update 操作不会受影响。

Gap Lock 锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。

 

2.3.3 Next-Key Lock 

Next-Key 锁,称为临键锁,它是 Record Lock + Gap Lock 的组合,用来锁定一个范围,并且锁定记录本身锁,它是一种左开右闭的范围,可以用符号表示为:(a,b]。

图片

为了更好的说明 Next-Key Lock 间隙锁,可以参照下面的顺序执行流和实例图:

加锁线程 sessionA 线程 B sessionB 线程 C sessionC 线程 D sessionD
#开启事务
begin;
     
加锁
select * from user
where age = 10 for share;
     
  #获取锁失败,insert 操作被堵塞
insert into user(id,age)
values(2,20);
   
    update user set name='name1'
where age = 10;
#查看 InnoDB 监视器中记录锁数据
show engine innodb statusG
提交事务 Gap Lock 被释放
commit
     
  被堵塞的 insert 操作执行 ok 被堵塞的 update 操作执行 ok  

图片

上图中,事务 A(sessionA)在加共享锁的时候产生了间隙锁(Gap Lock),事务 B(sessionB)对间隙中进行 insert 操作,需要先获取排他锁(X),导致阻塞。事务 C(sessionC)对间隙中进行 update 操作,需要先获取排他锁(X),导致阻塞。事务 D(sessionD)通过"show engine innodb statusG" 指令可以查看到间隙锁的存在。需要说明的,间隙锁只是锁住间隙内部的范围,在间隙外的 insert/update 操作不会受影响。

 

2.3.4 Insert Intention Lock   

插入意向锁,它是一种特殊的间隙锁,特指插入操作产生的间隙锁。为了更好的说明 Insert Intention Lock 锁,可以参照下面的顺序执行流和实例图:

加锁线程 sessionA 线程 B sessionB 线程 C sessionC
#开启事务
begin;
   
加锁
select * from user
where age = 10 for share;
   
  #获取锁失败,insert 操作被堵塞
insert into user(id,age) values(2,20);
 
    #查看 InnoDB 监视器中记录锁数据
show engine innodb statusG
commit 提交事务
Gap Lock 被释放
   
  #被堵塞的 insert 操作执行 ok
insert into user(id,age) values(2,20);
 

图片

 

三、乐观锁 & 悲观锁   

在 MySQL 中,无论是悲观锁还是乐观锁,都是人们对概念的一种思想抽象,它们本身还是利用 MySQL 提供的锁机制来实现的。其实,除了在 MySQL 数据,像 JAVA 语言里面也有乐观锁和悲观锁的概念。

  • 悲观锁,可以理解成:在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking),采用的是先获取锁再操作数据的策略,可能会产生死锁;

  • 乐观锁,是相对悲观锁而言,一般不会利用数据库的锁机制,而是采用类似版本号比较之类的操作,因此乐观锁不会产生死锁的问题;

 

四、死锁 & 死锁检测   

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。可以通过下面的指令查看死锁:

  • show engine innodb statusG

当出现死锁以后,有两种策略:

  1. 直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wAIt_timeout 来设置,InnoDB 中 innodb_lock_wait_timeout 的默认值是 50s。

  2. 发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其它事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启死锁检测。

 

五、总结   

本文基于 MySQL 8.0.30 版本和 InnoDB 引擎,对 MySQL 中的锁进行了讲解,每种锁都有其特定的使用场景。作为经常和 MySQL 打交道的 Java 程序员来说,对 MySQL 锁了解的越深,越可以帮助我们更好的去写出高性能的 SQL 语句。



Tags:MySQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  Search: MySQL  点击:(5)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  Search: MySQL  点击:(10)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  Search: MySQL  点击:(8)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  Search: MySQL  点击:(23)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10  Search: MySQL  点击:(5)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  Search: MySQL  点击:(26)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  Search: MySQL  点击:(43)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  Search: MySQL  点击:(51)  评论:(0)  加入收藏
为什么高性能场景选用Postgres SQL 而不是 MySQL
一、 数据库简介 TLDR;1.1 MySQL MySQL声称自己是最流行的开源数据库,它属于最流行的RDBMS (Relational Database Management System,关系数据库管理系统)应用软件之一。LAMP...【详细内容】
2024-02-19  Search: MySQL  点击:(37)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  Search: MySQL  点击:(53)  评论:(0)  加入收藏
▌简易百科推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  爱可生开源社区    Tags:MySQL   点击:(5)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  爱可生开源社区  微信公众号  Tags:MySQL   点击:(10)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  MySQL学习  微信公众号  Tags:MySQL   点击:(8)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  字节跳动技术团队    Tags:ByteHouse   点击:(23)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10    dbaplus社群  Tags:MySQL   点击:(5)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  转转技术  微信公众号  Tags:MySQL   点击:(26)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  数据库干货铺  微信公众号  Tags:MySQL   点击:(43)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  编程技术汇    Tags:MySQL   点击:(51)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  数据库干货铺  微信公众号  Tags:MySQL   点击:(53)  评论:(0)  加入收藏
mysql索引失效的场景
MySQL中索引失效是指数据库查询时无法有效利用索引,这可能导致查询性能显著下降。以下是一些常见的MySQL索引失效的场景:1.使用非前导列进行查询: 假设有一个复合索引 (A, B)。...【详细内容】
2024-01-15  小王爱编程  今日头条  Tags:mysql索引   点击:(82)  评论:(0)  加入收藏
站内最新
站内热门
站内头条