ACID特性

原子性 atomicity 事务是一个原子 操作,要不全部执行,要么全部不执行
持久性 durability 事务一旦提交,对数据库中数据的改变是永久的,后续的操作或故障不应该对其产生影响(例如其他事物会滚,不会影响该事物的修改结果)
隔离性 isolation 一个事务的执行不能被其他事务干扰
一致性 consistency 理解为数据的完整性,通过原子性,持久性,隔离性来保证

事务控制

并发事务的问题

更新丢失:当两个事务更新同一行记录,会产生更新丢失现象

  • 会滚覆盖
  • 提交覆盖

脏读:一个事务读取到另一个事务未提交的数据

不可重复读:一个事务中,多次读取同一行数据,数据内容不一致。
a事务执行过程中,多次查询一条数据,b事务对该行数据进行了更新并提交

幻读:一个事务中,相同条件,多次查询,查询结果数不一致
a事务执行过程中,多次查询表数据,b事务对表数据进行删除/添加操作,并提交

演进过程

排队

排他锁

读写锁

MVCC

事务隔离级别

mysql数据库通过事务隔离级别来解决并发事务问题(更新丢失、脏读、不可重复读、幻读)

隔离级别类型

image.png

读未提交

Read Uncommitted 读未提交:解决了回滚覆盖类型的更新丢失,但可能发生脏读现象,也就是
可能读取到其他会话中未提交事务修改的数据。

读已提交

Read Committed 读已提交:只能读取到其他会话中已经提交的数据,解决了脏读。但可能发生
不可重复读现象,也就是可能在一个事务中两次查询结果不一致。

可重复读

Repeatable Read 可重复读:解决了不可重复读,它确保同一事务的多个实例在并发读取数据
时,会看到同样的数据行。不过理论上会出现幻读,简单的说幻读指的的当用户读取某一范围的数
据行时,另一个事务又在该范围插入了新行,当用户在读取该范围的数据时会发现有新的幻影行。

可串行化

Serializable 串行化:所有的增删改查串行执行。它通过强制事务排序,解决相互冲突,从而解决
幻度的问题。这个级别可能导致大量的超时现象的和锁竞争,效率低下。

数据库的事务隔离级别越高,并发问题就越小,但是并发处理能力越差(代价)。
读未提交隔离级别最 低,并发问题多,但是并发处理能力好。

事务隔离级别和锁的关系:

  1. 事务隔离级别是SQL92定制的标准,相当于事务并发控制的整体解决方案,本质上是对锁和MVCC使

用的封装,隐藏了底层细节。

  1. 锁是数据库实现并发控制的基础,事务隔离性是采用锁来实现,对相应操作加不同的锁,就可以防止其他事务同时对数据进行读写操作。
  2. 对用户来讲,首先选择使用隔离级别,当选用的隔离级别不能解决并发问题或需求时,才有必要在开发中手动的设置锁。

MySQL默认隔离级别:可重复读
Oracle、SQLServer默认隔离级别:读已提交

mysql隔离级别控制

查看MySQL当前数据库的事务隔离级别命令如下:

  1. show variables like 'tx_isolation';
  2. select @@tx_isolation;

设置事务隔离级别可以如下命令:

  1. set tx_isolation='READ-UNCOMMITTED';
  2. set tx_isolation='READ-COMMITTED';
  3. set tx_isolation='REPEATABLE-READ';
  4. set tx_isolation='SERIALIZABLE';

锁机制和实战

锁分类

操作粒度

表锁
页锁
行锁
image.png

操作类型

读锁/共享锁
写锁/排他锁

操作性能

乐观锁
悲观锁

行锁原理

记录锁
间隙锁
记录锁+间隙锁

悲观锁

指在数据处理过程中,将数据处于锁定状态,一般使用数据库的锁机制实现。
行锁、表锁、读锁、写锁、共享锁、排他锁都是悲观锁

乐观锁

乐观锁是相对于悲观锁而言,不是数据库提供的功能,需要开发者自己实现。
实现的关键点:冲突的检测

乐观锁实现原理:

  • 使用版本字段(version),每次更新版本+1
  • 使用时间戳,更新时比较记录时间是否一致

读锁

针对同一份数据,多个读操作可以同时进行

写锁

当前操作没有完成前,阻塞其他读锁和写锁

死锁解决方案

  1. 表锁死锁
  1. 行级锁死锁
  1. 共享锁转化为排他锁
  1. 死锁排查
  • 查看死锁日志

通过show engine innodb status\G命令查看近期死锁日志信息。
使用方法:1、查看近期死锁日志信息;2、使用explain查看下SQL执行计划

  • 查看锁状态变量

通过show status like’innodb_row_lock%‘命令检查状态变量,分析系统中的行锁的争夺
情况
Innodb_row_lock_current_waits:当前正在等待锁的数量
Innodb_row_lock_time:从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg: 每次等待锁的平均时间
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次锁的时间
Innodb_row_lock_waits:系统启动后到现在总共等待的次数
如果等待次数高,而且每次等待时间长,需要分析系统中为什么会有如此多的等待,然后着
手定制优化。