MySQL事务和锁

什么是数据库的事务

 ACID的特性

事务的隔离级别

隔离水平及可能出现的问题:

并发事务的控制方式

1、MVCC(多版本并发控制):

2、锁机制:

InnoDB 实现 MVCC 机制

共享锁和排他锁

间隙锁

意向锁

死锁

如何解决死锁


什么是数据库的事务

  • 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库执行操作组成。

 ACID的特性

  • A(atomicity),原子性。整个数据库事务是不可分割的工作单位。要么成功全部提交,要么失败全部回滚.
  • C(consistency),一致性。事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。
  • I(isolation),隔离性。事务与事务之间互相隔离互不影响.
  • D(durability) ,持久性。事务一旦提交,数据的改变就是永久性的,即使发生宕机等故障,也不会对其有任何影响。

事务的隔离级别

  • 读未提交: 未提交的事务作出的变更,也能被其他事务读取.
  • 读已提交: 事务的变更提交后,才能被其他事务读取.
  • 可重复读: 事务读取的数据都与事务开启时读取的数据一致.(MySQL InnoDB 默认隔离级别)
  • 串行化: 有读写冲突时,必须等之前的事务提交完成之后才开始执行.

隔离水平及可能出现的问题:

串行化 >

可重复读 >

读已提交 >

读未提交

幻读

幻读

幻读

不可重复读

不可重复读

脏读

幻读:  在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象. 

eg: 事务1读取某个范围的数据, 事务2在这个范围新增了一条数据,事务1再读发现多了一条数据.

不可重复读: 在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。

eg: 事务1读取到 a =1,  事务2 修改 a = a-1, 事务1 再读取 a = 0.

脏读: 在一个事务修改未提交,就被另一个事务读取.

eg: 事务1读取到 a = 1,修改 a = a - 1, 事务2读取到 a = 0, 但是事务1由于异常回滚到 a = 1,事务2就出现「脏读」.

并发事务的控制方式

MySQL 中并发事务的控制方式无非就两种: 和 MVCC。锁可以看作是悲观控制的模式,多版本并发控制(MVCC,Multiversion concurrency control)可以看作是乐观控制的模式

1MVCC(多版本并发控制):

  • MySQL中通过MVCC来实现读写并发,确保事务之间的隔离性。在InnoDB存储引擎中,每行数据都会保存一个版本号,当一个事务开始时,会生成该事务的事务ID,并在进行写操作时保存该操作前的数据版本。这样,其他事务仍然可以读取之前的数据版本,从而实现了读写并发。
  • MVCC可以减少读写冲突,提高并发性能,同时保证了事务的一致性和隔离性

2、锁机制:

  • MySQL中使用锁机制来保证事务的原子性和隔离性。主要包括行级锁和表级锁。
  • 行级锁:在InnoDB存储引擎中,默认使用行级锁,可以在事务中对某行数据进行加锁,避免其他事务对该行数据的修改操作。
  • 表级锁:对整个表进行锁定,会限制其他事务对表中任何数据的访问或修改。
  • 锁机制可以确保数据的完整性,但在高并发情况下可能会导致性能问题,因此结合MVCC可以提高并发性能。

MySQL通过MVCC和锁机制来解决事务问题,保证了事务的隔离性、一致性和并发性能。MVCC减少了读写冲突,提高了并发性能,而锁机制则保证了数据的完整性和事务的原子性。在实际应用中,根据具体场景选择合适的锁策略和优化MVCC配置可以更好地提升数据库性能和稳定性。

InnoDB 实现 MVCC 机制

InnoDB 通过对一个数据行维护多个版本的数据来实现的,当一个事务对数据进行修改是,MVCC会为该事务创建一个数据快照,而不是直接修改实际的数据行.

读:  不晚于事务开始时刻的该数据行的最新快照

写:  会在该修改数据行创建一个新的版本并写入数据, 如果事务提交会将版本号更新入原数据行,回滚则删除该版本.原始版本数据依然存在,供其他事务读取快照,保证了其他事务不受读操作影响.

共享锁和排他锁

共享锁, lock in share mode 其他事务对该版本数据可读不可写

排他锁, for update 其他事务 对该版本数据不可读也不可写 不影响select,select会从快照中读.

间隙锁

InnoDB 在可重复读隔离级别下,会用 Next_key Lock 对数据行进行加锁,事务就不能在这个间隙插入数据,防止幻读的发生.

意向锁

意向锁是按事务要求对行或表申请共享锁(读锁)或排他锁(写锁).

对行申请排他锁: select id from tableName where id = 1 for update

对表申请共享锁: lock tables tableName read;

死锁

当两个以上事务,同时持有对方需要的锁,并需要对方持有的锁,产生循环依赖.导致两个事务一直在等待对方释放锁.

如何解决死锁

  1. InnoDB 超时机制,当一个或多个事务锁超时会自动回滚并释放锁,使其他事务可以继续进行.
  2. 手动解决
  • Kill 阻塞线程,让其他线程获取资源
  • select concat('kill ' , id, ';')  from information_schema.processlist where Command != 'Sleep' and Time > 300 order by Time desc;

  • Kill 等待线程,把资源让给阻塞线程.
  • select concat('kill ' , id, ';')  from information_schema.processlist where id in ( select trx_mysql_thread_id from information_schema.INNODB_TRX where trx_state ='LOCK WAIT' );
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值