深入理解mysql事务隔离与锁机制
2026-01-06 10:21:56 0 举报
AI智能生成
本文档深入解析了MySQL中的事务隔离和锁机制,探讨了MySQL为保证数据一致性、有效隔离并发事务而采取的核心机制。介绍了包括读未提交(RU)、读已提交(RC)、可重复读(RR)、串行化(S)在内的四种隔离级别,并详述了每种隔离级别下的潜在问题及其应用场景。同时,深入剖析了MySQL所采用的锁机制,包括乐观锁、悲观锁、行锁、表锁等,讲解了这些锁的使用场景和性能影响,以及其在高并发环境下的表现。
作者其他创作
大纲/内容
事务
什么是事务?<br>
数据库操作中一组sql语句组成的逻辑处理单元,它由一个或者多个sql语句组成。操作要么全部成功,要么全部失败。<br>
事务特性:ACID<br>
A(原子性)<br>
核心:事务的所有操作要么全部成功,要么全部失败回滚。<br>实现:通过mysql的undo log(回滚日志)实现,如果事务失败,mysql通过undo log 将数据恢复到事务开始前的状态。<br>
C(一致性)<br>
核心:事务执行前后,数据库必须从一个一致性状态变换到另一个一致性状态。<br>原子性,隔离性,持久性都是为了保证事务的最终一致性而存在的<br>
I(隔离性)<br>
核心:一个事务所做的修改在最终提交之前,对其他事务是<font color="#e74f4c">不可见的,</font><font color="#000000">多个并发事务之间要相互隔离,防止数据不一致。<br></font>问题:如果没有隔离性,会引发脏读,不可重复读,幻读等问题。<br>实现:mysql通过mvcc和锁机制来实现,mysql不同的事物隔离级别(读未提交,读已提交,可重复读,串行化)来平衡隔离性和并发性能。<br>
D(持久性)<br>
核心:一旦事物提交后,其所做的修改就是永久保存到数据库中,即使系统发生崩溃,数据也不会丢失。<br>实现:通过redo log实现,修改数据时,mysql会先写redo log,<br>
查看当前数据库事务命令
mysql5.7:show variables like 'tx_isolation'<br>
msyql8.0:show variables like '%isolation%'<br>
设置当前链接事务级别命令
mysql5.7:set tx_isolation='repeatable-read'<br>
mysql8.0:set transaction_isolation='repeatable-read'<br>
并发事务处理带来的问题<br>
丢失更新或脏写<br>
最后的更新覆盖之前事务所做的更新<br>
脏读
事务A 读取到了事务B已经修改但尚未提交的数据<br>
不可重复读
事务A 中相同的查询每次结果都不相同,不符合隔离性要求
幻读
事务A读取到了B事务新增的数据。<br>
事务隔离级别
读未提交(read uncommitted)<br>
读已提交(read committed)<br>
可重复读(repeatable read)<br>
mysql默认事务隔离级别
串行化(serializable)<br>
锁
什么是锁?<br>
锁是计算机协调多个进程或线程并发访问某一共同资源的机制<br>
锁分类
性能上区分
乐观锁
用版本对比来实现
建议用于读多写少的场景,写多话版本变化太快,等待太长,开销大
悲观锁
建议用于读少写多的场景
数据库操作类型<br>
读锁(共享锁 S)<br>
针对同一份数据,多个读操作可以同时进行而不会相互影响<br>
写锁(排它锁)<br>
当写操作没有完成前,会阻塞其他写锁与读锁<br>
表锁
特点:每次操作锁住整张表,开销小,加锁快,不会出现死锁,锁粒度大,发生锁冲突的概率最高,并发度最低。一般用在整张表数据迁移的场景。<br>
手动增加表锁命令
lock table 表名称 read(write),表名称2 read(write)<br>
查看表锁命令
show open tables<br>
删除表锁命令
unlock tables
行锁
特点:每次操作锁定一行数据,开销大,加锁慢,会出现死锁,锁粒度小,并发度高。<br>
innodb的行锁是作用在索引项上的,不是针对记录行加锁,索引失效在RR隔离级别下会表现为表锁效果。<br>
RR级别下:如果查询字段没有索引,全表扫描,为了防止幻读,由于间隙锁与临键锁的原因,会锁住全部行,效果相当于表锁<br>
RC级别下:由于没有间隙锁,只锁定实际符合条件的行,不会影响插入操作。<br>
间隙锁
锁的就是两个值之间的空隙,<font color="#e74f4c">在可重复读隔离级别下生效</font>,能一定程度帮组可重复读解决幻读问题。<br>
临键锁
行锁与间隙锁的组合。<br>
MDL锁 <br>
防止事务过程中DDL操作带来的数据不一致<br>
意向锁(表级锁) <br>
IS(意向共享锁)<br>
给数据行加读锁前先取得该表的IS锁,防止事务过程中DDL操作带来的数据不一致<br>
IX(意向排它锁)<br>
给数据行加写锁前先取得该表的IX锁,防止事务过程中DDL操作带来的数据不一致
锁优化
通过查看innodb_row_lock来分析行锁争夺情况<br>
show status like 'innodb_row_lock%'<br>
innodb_row_lock_current_waits:当前正在等待锁定的数量<br>
<font color="#e74f4c">innodb_row_lock_time</font>:从系统启动到现在锁定总时间长度<br>
<font color="#e74f4c">innodb_row_lock_time_avg</font>:每次等待所花平均时间<br>
innodb_row_lock_time_max:从系统启动到现在锁等待最长的一次花费时长<br>
<font color="#e74f4c">innodb_row_lock_waits</font>:等待总次数<br>
锁优化建议
尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁。<br>
合理设计索引,尽量缩小锁范围。<br>
尽可能减少检索条件范围,避免间隙锁<br>
尽可能低级别事务隔离<br>
尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量做后执行。<br>
收藏
收藏
0 条评论
下一页