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

数据库事务:

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

事务的作用

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锁
在这里插入图片描述
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.使用这个命令,只能查看这个账户下操作的线程
在这里插入图片描述
2.在用kill id,杀死Command为Query 的进程即可。

发布了50 篇原创文章 · 获赞 13 · 访问量 2370

猜你喜欢

转载自blog.csdn.net/endless_Y/article/details/105233883