欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【面试高频!】数据库事务/事务的作用/数据库事务ACID属性 / 特性/事务的隔离性/数据库事务隔离级别/ 数据库的隔离级别导致问题/数据库事务的使用/mysql的事务死锁/ 快速解决mysql死锁问

程序员文章站 2022-05-09 17:38:16
...

数据库事务:

  • 针对数据库的某一组操作要么全部成功,要么全部失败。

事务的作用

1:保证数据的完整性,失败后可以恢复到原来状态
2:事务与事务之间互不干扰,这样数据会更加安全

数据库事务ACID属性 / 特性

原子性(Atomicity)要么全部完成,要么全部不完成。

一致性(Consistency)事务必须始终保持系统处于一致性。

隔离性(Isolation)隔离执行事务,使它们好像是系统在给定时间内执行的唯一操作。

持久性(Durability)事务完成后,该事务对数据库的更改持久保存在数据库中。

事务的隔离性

对于同时运行的多个事务,当这些事物访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。

不可重复读:一个事务T1读事务T2的数据,多次内数据不一样。

幻读:事务T1对自己某一项的数据全部修改后T2又对数据进行修改,T1在读后发现有一条不一样。

脏读:一个事务T1已经读到了事务T2未提交的数据,如果T2事务不提交,那么T1再次读到的数据跟前一次不一样。

数据库事务隔离级别

Mysql四种,Mysql默认Repeatable read.
Oracle两种(Read Commited,Serializable)Oracle默认Read committed。

事务隔离

READ UNCOMMITTED:使用查询语句不会加锁,可能读取未提交的行。

READ COMMITTED:只对记录加记录锁,不会在记录之间加间隙锁,允许新的记录插入到被锁记录的附近,多次使用查询语句时,可能得到不同的结果。

REPEATABLE READ:多次读取同一范围的数据会返回第一次查询的快照,不会返回不同的数据行,可能发生幻读。

SERIALIZABLE:InnoDB隐式地将全部的查询语句加上共享锁,解决幻读的问题。

隔离级别的语法

  1:查看
    select @@tx_isolation;
  2:设置
    set transaction isolation leval 级别;
  3:jdbc设置隔离级别
    connection.setTransactionIsolation(1|2|4|8);

数据库的隔离级别导致的问题

脏读

一个事务对数据进行了修改,但未提交,另一个事务可以读取到未提交的数据。如果第一个事务回滚了,第二个事务读到的了脏数据。

不可重复读

一个事务中发生了两次读操作,第一次读操作和第二次读操作时间,另外一个数据对数据进行了修改,这时候两次读取的数据不一致。

幻读

第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围内增加了一条数据,这时候第一个事务就会丢失对新增数据的修改。

数据库事务的基本使用

    mysql--> dbms-->数据库事务自动提交
    一个crud事务就是一个事务,当有一个操作是会自动提交事务,提交后的数据持久改变,
    刻入磁盘,当发生异常,设置回滚,数据库就不会有所改变
    没有异常  commit
    抛出异常  rollback

在MySQL数据库中查看当前事务的隔离级别:

select @@tx_isolation;

在MySQL数据库中设置事务的隔离级别:

set [glogal | session] transaction isolation level 隔离级别名称;
set tx_isolation=’隔离级别名称;’

mysql的事务死锁

锁:

锁并不是和事务绑定一起的,不同的语句可能锁集不同,但是事务的隔离级别会影响锁的范围.
不在事务当中的UPDATE,INSERT等也都会用到锁.

锁的范围
1.record lock:记录锁

当我们加入select * from orders whereid = 1 for update这样会阻止其他语句增删改这条数据.

2.gap lock:间隙锁

间隙锁,这个锁会锁住该数据上一个邻近位置(根据索引或者主键)与下一个邻近位置之间的范围.(对于索引而言)
锁住区间范围(邻近的index-1,index);

3.next-key lock:gap lock + recordlock

事务级别最低为repeatable read,会启用这个锁,如果低于这个级别会不起用这个锁.
因此锁的范围就变为了(邻近的index-1,index];

REPEATABLE READ下的加锁规则

原则 1:加锁的基本单位是 next-key lock。希望你还记得,next-key lock 是前开后闭区间。

原则 2:查找过程中访问到的对象才会加锁。

优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。

优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,nextkeylock 退化为间隙锁。

一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止

死锁

死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待.

等待图(wait-for-graph)可以用来检测死锁,通过深度优先算法实现,只要图中存在循环的回路.那么存在死锁.
解决死锁时会回滚当中undo量最小的一个事务。

意向锁

意向锁是表级锁,指明事务在将要对表中的行加哪种意向锁.
IS:指明事务将会在表中的行加共享锁.
IX:指明事务将会在表中的行加排它锁.

意向锁的意义:表明某个事务正在锁或者将要锁表中的一行数据.
意向锁不会阻塞除全表操作以外的(例如:LOCK TABLES … WRITE)任何请求
如果一个事务想在表中行加S锁,那么必须先获取IS锁
如果一个事务想在表中行加X锁,那么必须先获取IX锁
【面试高频!】数据库事务/事务的作用/数据库事务ACID属性 / 特性/事务的隔离性/数据库事务隔离级别/ 数据库的隔离级别导致问题/数据库事务的使用/mysql的事务死锁/ 快速解决mysql死锁问
MDL锁(Meta Data Lock)
MDL是意向锁的实现,这个锁是表级锁,MDL不需要显式使用,在访问一个表的时候会被自动加上。DML会加一个读锁。

我们经常遇到线上由于业务需要加字段,这个是个比较危险的操作,我们一般选择在业务的低峰期执行。

DDL的操作流程:

  1. 拿MDL写(X)锁
  2. 降级成MDL读(S)锁
  3. 真正做DDL
  4. 升级成MDL写(X)锁
  5. 释放MDL锁

如果DDL拿不到MDL写锁,会一直等待,并阻塞在其之后的DML。

快速解决mysql死锁问题

1.首先查看mysql当前的全部线程 使用命令

show processlist;

2.使用这个命令,只能查看这个账户下操作的线程
【面试高频!】数据库事务/事务的作用/数据库事务ACID属性 / 特性/事务的隔离性/数据库事务隔离级别/ 数据库的隔离级别导致问题/数据库事务的使用/mysql的事务死锁/ 快速解决mysql死锁问
2.在用kill id,杀死Command为Query 的进程即可。