MySQL事务隔离级别与锁机制

文章介绍了数据库中事务的概念,包括ACID属性,以及并发事务处理时可能出现的问题,如脏读、不可重复读和幻读。事务隔离级别,如读未提交、读已提交、可重复读和可串行化,被用来解决这些问题。此外,还详细讨论了锁的类型,如乐观锁、悲观锁、表锁和行锁,以及它们在并发控制中的作用。最后,提出了锁优化的一些建议。
摘要由CSDN通过智能技术生成

概述

数据库一般会并发执行多个事务,多个事务可能会并发的对相同的数据进行增删改查的操作,可能就会导致数据的脏写脏读不可重复读幻读这些问题。为了解决多事务并发问题,数据库设计了事务隔离机制锁机制MVCC多版本并发控制隔离机制来解决多事务并发问题。

事务

事务是由一组SQL语句组成的逻辑处理单元,事务具有ACID属性:

  • 原子性(Atomicity):事务是一个原子的单元操作,对其数据的修改,要么全部执行,要么全部不执行

  • 一致性(Consistent):在事务开始和完成时,数据必须保持一致的状态。所有相关数据的规则必须应于事务的修改以保持数据的完整性

  • 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作的影响“独立”环境执行,事务处理过程中的中间状态对外部是不可见的。

  • 持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现了系统故障也能够保持

并发事务处理带来的问题

更新丢失(Lost Update)或脏写

当两个或多个事务对同一条记录数据进行更新操作时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题,最后的更新覆盖了由其他事务更新的操作。

脏读

一个事务在多一条记录做修改,在这个事务完成并提交之前,这条记录的数据就处于不一致的状态,若此时有其他事务来读取这条记录,如果不加控制的情况会出现“脏读”数据,如果对该数据进行后续的操作就会产生未提交的数据依赖关系,这种现象称为“脏读”。

不可重读(Non-Repeatable Reads)

一个事务在读取某些数据后的某个时候在此读取之前读过的数据,确发现其读取的数据已经发生了改变或默写记录已经被删除了,这种现象被称为”不可重读“。

幻读(Phantom Reads)

一个事务按相同的查询语句重新读取以前检索过的数据,确发现其他事务插入了满足其条件的新数据,这种现象称为“幻读”。

事务隔离级别

“脏读”、“不可重复读”、“幻读”,是数据库读一致性问题,数据库提供了事务隔离机制来解决,事务隔离级别:读未提交(Read uncommitted)、读已提交(Read committed)、可重复读(Repeatableread)、可串行化(Serializable),数据库的隔离级别越严格,并发副作用越小,Mysql数据库默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认使用Mysql设置的隔离级别,如果Spring设置了就用设置的隔离级别

隔离级别

脏读(Dirty Read)

不可重复读(NonRepeatable Read)

幻读(Phantom Read)

读未提交(Read uncommitted)

可能

可能

可能

读已提交(Read committed)

不可能

可能

可能

可重复读(Repeatableread)

不可能

不可能

可能

可串行化

(Serializable)

不可能

不可能

不可能

常用命令

查看数据库的事务隔离级别命令

show variables like 'tx_isolation';

设置数据库的事务隔离级别

set tx_isolation='REPEATABLE-READ';

锁详解

锁是计算机协调多个进程或线程并发访问某一资源的机制。

锁分类

  • 性能上分:乐观锁(用版本号对比来实现)和悲观锁

  • 操作粒度上分:表锁行锁

  • 操作类型分:读锁写锁(都是悲观锁)、意向锁。

读锁(共享锁,S锁(Shared)):针对同一份数据,多个读操作可以同时进行而不会互相影响。

写锁(排它锁,X锁(eXclusive)):当前操作没有完成,他会阻断其他写锁或读锁,数据修改的操作都会加写锁。

意向锁(Intention Lock):I锁,针对表锁,主要是为了提高加表锁的效率,是Mysql自己加的,当有事务给表的数据加了共享锁或排它锁,同时会给表设置一个标识代表已经有了行锁,直接读取这个标识就可以确定自己该不该加表锁。主要分为:

意向共享锁(IS锁):对整个表加共享锁之前,需要先获取到意向共享锁。

意向排它锁(IX锁):对整个表加排它锁之前,需要先获取到意向排它锁。

表锁

每次操作锁住整张表。开销小,加锁块;不会出现死锁;锁粒度大,发生锁冲突的概率高,并发低。一般用于整张表的数据迁移场景。

常用命令

手动增加表锁

#添加读锁
lock table [表名] read;
#添加写锁
lock table [表名] write;
#查看表上加过的锁
show open tables;
#删除表锁
unlock tables;

总结

对MyISAM表的读操作(加读锁) ,不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。

对MylSAM表的写操作(加写锁) ,会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作

行锁

每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发读高。一个session开启事务更新不提交,另一个session更新同一条记录会阻塞,更新不同记录不会阻塞,即读锁会阻塞写锁,但是不会阻塞读锁,而写锁会阻塞读锁和写锁

锁优化建议

  • 尽可能让所有数据检查都通过索引来完成,避免无索引行锁升级为表锁。

  • 合理设计索引,尽量缩小锁的范围。

  • 尽可能减少检索条件范围,避免间隙锁。

  • 尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行。

  • 尽可能低级别事务隔离。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值