【MySQL】update没加索引会锁全表?

前言

有个朋友遇到了这么一件事,在线上执行一条 update 语句修改数据库数据的时候,where 条件没有带上索引,导致业务直接崩了,被老板教训了一波。

我们一起来分析下原因:

  • 为什么会发生这种的事故?
  • 又该如何避免这种事故的发生?

说个前提,接下来说的案例都是基于 InnoDB 存储引擎,且事务的隔离级别是可重复读。

为什么会发生这种的事故?

InnoDB 存储引擎的默认事务隔离级别是「可重复读」,但是在这个隔离级别下,在多个事务并发的时候,会出现幻读的问题,所谓的幻读是指在同一事务下,连续执行两次同样的查询语句,第二次的查询语句可能会返回之前不存在的行。

因此 InnoDB 存储引擎自己实现了行锁,通过 next-key 锁(记录锁和间隙锁的组合)来锁住记录本身和记录之间的“间隙”,防止其他事务在这个记录之间插入新的记录,从而避免了幻读现象。

当我们执行 update 语句时,实际上是会对记录加独占锁(X 锁)的,如果其他事务对持有独占锁的记录进行修改时是会被阻塞的。另外,这个锁并不是执行完 update 语句就会释放的,而是会等事务结束时才会释放。

在 InnoDB 事务中,对记录加锁带基本单位是 next-key 锁,但是会因为一些条件会退化成间隙锁,或者记录锁。加锁的位置准确的说,锁是加在索引上的而非行上。

比如,在 update 语句的 where 条件使用了唯一索引,那么 next-key 锁会退化成记录锁,也就是只会给一行记录加锁。

这里举

<think> 首先,用户的问题是:“我想查找在不表的情况下添索引的方法 请问不表添索引的方法”。用户想在MySQL中不表添索引。 从系统指令中,我需要参考提供的站内引用。这些引用是: - 引用[1]: 提到了使用ALTER TABLE语句添索引时不表的方法,使用ALGORITHM=INPLACE和LOCK=NONE。 - 引用[2]: 详细解释了ALGORITHM和LOCK参数的意义,包括ALGORITHM=INPLACE和COPY的过程,以及LOCK的四种模式:DEFAULT, NONE, SHARED, EXCLUSIVE。 - 引用[3]: 强调了添唯一索引时可能需要全表扫描验证唯一性。 - 引用[4]: 提到MySQL 5.6.7之后支持Online DDL技术,允许添索引时与DML操作并发。 用户的需求很清楚:找出在不表的情况下添索引的方法。所以,我需要基于引用内容回答。 关键点是使用Online DDL技术,这在MySQL 5.6及以上版本支持。具体命令是: ```sql ALTER TABLE table_name ADD INDEX index_name (column_name), ALGORITHM=INPLACE, LOCK=NONE; ``` 引用[1]直接给出了这个命令。引用[2]解释了ALGORITHM=INPLACE和LOCK=NONE的含义。ALGORITHM=INPLACE表示在原始表上进行操作,而不是创建临时表;LOCK=NONE表示允许在DDL期间进行读写操作。 但引用[2]也提到,添唯一索引时可能需要全表扫描验证唯一性,这可能会影响性能或表。引用[3]也指出了这一点。 引用[4]确认了MySQL 5.6.7之后支持Online DDL。 所以,我的回答应该: - 解释Online DDL的基本概念。 - 给出具体的SQL命令。 - 讨论限制条件,如MySQL版本要求(5.6及以上),以及对于唯一索引的潜在问题。 - 确保引用正确添引用标识,如[^1]、[^2]等。 回答结构应该清晰: 1. 介绍方法:使用Online DDL。 2. 提供示例命令。 3. 解释参数:ALGORITHM和LOCK。 4. 注意事项:版本兼容性、索引类型(唯一索引可能表)、性能影响。 5. 自然地添相关问题。 系统指令要求生成相关问题,所以在末尾添相关问题。 另外,指令说:“回答中引用的段落末尾自然地添引用标识”,所以在解释完每个点后添引用。 最后,使用中文回答。 大纲回答: - 开头:直接回答用户问题,说明MySQL 5.6及以上支持不表添索引的方法。 - 方法:使用ALTER TABLE命令指定ALGORITHM=INPLACE和LOCK=NONE。 - 示例命令:基于引用[1]。 - 解释:简要解释ALGORITHM和LOCK,参考引用[2]。 - 注意事项: - MySQL版本必须5.6以上(参考引用[4])。 - 对于唯一索引或主键索引,可能需要全表扫描,可能会表或有性能影响(参考引用[2]和[3])。 - 在某些情况下,如添唯一索引时,LOCK=NONE可能失败(参考引用[2])。 - 结束:总结最佳实践。 - 相关问题:生成几个相关问题。 相关问题想法: 1. MySQL Online DDL支持哪些操作? 2. 如何检查MySQL版本是否支持Online DDL? 3. 添索引时避免表的替代方法? 4. 为什么添唯一索引有时需要表? 5. 优化Online DDL性能的方法? 确保回答真实可靠,基于提供的引用。 </think> ### MySQL表添索引的方法 在MySQL中,不表添索引主要通过**Online DDL(Data Definition Language)技术**实现,该技术自MySQL 5.6版本起支持。Online DDL允许你在执行添索引等DDL操作时,同时允许并发读写操作(如SELECT、INSERT、UPDATE、DELETE),从而避免表导致的服务中断。以下是具体方法、步骤和注意事项,基于您的需求整理。 #### 1. **核心方法:使用 ALGORITHM=INPLACE 和 LOCK=NONE** 在MySQL 5.6及以上版本中,可以通过`ALTER TABLE`命令指定`ALGORITHM=INPLACE`和`LOCK=NONE`来实现不表添索引。命令语法如下: ```sql ALTER TABLE `table_name` ADD INDEX `index_name` (`column_name`), ALGORITHM=INPLACE, LOCK=NONE; ``` - **`ALGORITHM=INPLACE`**:表示直接在原表上操作,无需创建临时表。这减少了IO和存储开销,具体步骤包括: - 创建索引数据字典。 - 共享表(仅禁止数据修改操作(DML),但允许查询)。 - 读取聚簇索引,构造并插入新索引。 - 等待所有只读事务提交。 - 完成索引创建。[^2] - **`LOCK=NONE`**:表示允许在DDL操作期间进行并发读写操作。如果操作不支持这种模式(如某些索引类型),命令会失败而不影响表。[^2] 示例:假设需为表`users`的`email`列添普通索引(非唯一索引),命令为: ```sql ALTER TABLE `users` ADD INDEX `idx_email` (`email`), ALGORITHM=INPLACE, LOCK=NONE; ``` #### 2. **适用条件与注意事项** - **MySQL版本要求**:仅MySQL 5.6.7及以上版本支持Online DDL(即添索引时不表)。低于此版本的操作会表,阻塞所有写入操作。[^4] - **索引类型限制**: - **普通索引(非唯一)**:通常支持`ALGORITHM=INPLACE`和`LOCK=NONE`,操作期间允许读写。 - **唯一索引或主键索引**:添时可能触发全表扫描以验证唯一性,这有时会导致表或操作失败,即使指定了`LOCK=NONE`。例如: ```sql ALTER TABLE `users` ADD UNIQUE INDEX `idx_email_unique` (`email`), ALGORITHM=INPLACE, LOCK=NONE; ``` 这种情况下,如果表数据量过大,MySQL可能退化为`ALGORITHM=COPY`(表模式),建议在低峰期操作或分步验证。[^3][^2] - **操作失败处理**:如果`LOCK=NONE`无法满足(如唯一索引冲突),MySQL会报错并中止操作,避免表风险。此时可改用`LOCK=SHARED`(允许读但禁止写)或重试。[^2] - **性能影响**:Online DDL虽不表,但可能因资源竞争导致查询变慢。建议监控服务器负载,并在业务低峰期操作。[^1][^3] #### 3. **最佳实践总结** - **步骤建议**: 1. 确认MySQL版本(运行`SELECT VERSION();`),确保为5.6或更高。 2. 对于非唯一索引,直接使用`ALGORITHM=INPLACE, LOCK=NONE`。 3. 对于唯一索引,先测试小表或使用`LOCK=SHARED`(允许读但禁止写)作为备选。 4. 操作前备份数据。 - **优势**:此方法避免了传统表(如`ALGORITHM=COPY`)的缺点,如存储翻倍和IO开销。[^2] - **风险提示**:在高并发环境中,Online DDL可能延长操作时间。使用工具如`pt-online-schema-change`(Percona Toolkit)可作为备选方案。[^1] 通过以上方法,您可以在不表的情况下安全添索引,提升数据库可用性。实际操作前,建议在测试环境验证。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术杠精

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值