10分钟快速了解MySQL事务与锁

本文深入探讨了数据库事务的ACID特性及其对并发控制的影响,并详细介绍了MySQL如何通过不同类型的锁来实现事务隔离级别的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在数据库中,以事务为单位去执行一组蕴含特定功能的SQL,可以比较安全地实现用户的操作需求。


所谓的“安全地实现”,比较书面的说法就是事务的ACID特性。

Atomicity原子性:all or nothing,由Redo & Undo实现。

Consistency一致性:事务执行前后完整性约束没有被破坏,由Undo实现。

拓展阅读:

一致性非锁定读:http://blog.youkuaiyun.com/leonpenn/article/details/74923377

MVCC:http://blog.youkuaiyun.com/leonpenn/article/details/72730218

Isolation隔离性:一个事务的修改对其他事务不可见,由Lock实现。

Durable持久性:Committed的数据变更将肯定保存,由Redo实现。



同其他数据库一样,MySQL是一个共享资源库,而共享就会带来多用户并发执行事务的问题。


而不受控制的并发就会带来脏读,不可重复读,幻读的问题/现象。

脏读的问题:当前事务读取到其他并发事务尚未Commit的数据;

不可重复读(提交读):当前事务可以读取到其他并发事务Commit的数据,带来了一个现象:两次读取同一行记录,获取了不同的数据。

幻读:当前事务可以读取到其他并发事务Commit的数据,带来了另外一个现象:两次读取同一个范围的记录,获取了更多的行记录。


为了解决这些问题或避免这些现象,就需要引入隔离级别对并发进行控制。

完全不受控制的并发类似于最低隔离级别Read Uncommitted。在SQL标准中,针对其带来的三个问题可以分别实施更高的隔离级别:Read Commited、Repeatable Read、Serializable 来解决。

MySQL默认隔离级别为Repeatable Read,已通过Next-Key Lock的方式一并解决了幻读的问题,达到了SQL标准中的Serializable。

生产环境中考虑到实际业务场景及性能的要求,多设置为Read Commited。值得一提的是,提交读的触发点是Commit或DDL语句(DDL隐含Commit操作:step1、Commit;step2、DDL;step3:Commit)。


上面讲到的不同的事务隔离级别,在MySQL内部是通过对锁的不同应用来实现的。


这就要提到中文中的“锁”,在数据库层面指代两个意思:lock和latch。前者的对象是事务,后者的操作对象主要集中于数据库内部资源。


根据不同的SQL语句会自动请求不同的Lock,锁处理机制以锁之间的兼容性来确定事务的并发处理方式。处理时具体信息参考如下:

(1)锁的类型:

IS意向共享锁(施加在数据行所在的表上)

IX意向排他锁(施加在数据行所在的表上)

S行级共享锁(施加在数据行上,需要先取得所在表的IS锁)

X行级排他锁(施加在数据行上,需要先取得所在表的IX锁)

(2)兼容性:X不兼容一切锁;IX不兼容S、X,但兼容意向锁;S不兼容X、IX,但兼容S、IS;IS仅仅不兼容X;


也可参考我翻译的官方手册的相关章节:http://blog.youkuaiyun.com/leonpenn/article/details/73920445


除了系统自动加锁外,也可以进行手动加锁:
select ... ... for update;
select ... ... lock in share mode;

(注意使用前先通过begin开启事务或设置autocommit=0)


锁的不同实现:

Record Lock:InnoDB层实现,锁定记录本身。Read Commited模式仅采用此方式

Gap Lock:InnoDB层实现,包含记录前后间隙但不含记录本身。Repeatable Read模式独有

Next-Key Lock:InnoDB层实现,Record Lock + Gap Lock。Repeatable Read模式独有

MDL:由Server层实现,保护select操作不被DDL影响


试想这样一种情况,在两个及两个以上的事务并发执行的时候,有可能事务之间都持有对方需要的锁,导致互相等待,这就是所谓的死锁。直到超时时间超过了innodb_lock_wait_timeout所定义的时间,才会自动回滚其中代价较小的事务,解开死锁。


当死锁发生时,如下语句可以查看最新检测到的死锁情况

show engine innodb status \G

--------------
LAST DETECTED DEADLOCK
--------------

或者开启参数:innodb_print_all_deadlocks;将会在错误日志内记录所有的死锁信息;




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值