【MySQL性能优化】- MySQL事务级别与锁机制

news2024/9/24 13:15:11

MySQL事务级别与锁机制

😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 博客首页   @怒放吧德德  To记录领地
🌝分享学习心得,欢迎指正,大家一起学习成长!
转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

在这里插入图片描述

文章目录

  • MySQL事务级别与锁机制
    • 简介
    • 事务及ACID
      • 并发事务带来的问题
        • 丢失修改(Lost Modify)或脏写
        • 脏读(Dirty reads)
        • 不可重复读(Non-repeatable reads)
        • 幻读(Phantom reads)
      • 事务的隔离级别
    • 锁机制
      • 锁分类
      • 表锁
        • 案例分析
      • 行锁
        • 案例分析
      • 行锁与事务隔离机制案例
        • 读未提交 (READ UNCOMMITTED)
        • 读已提交 (READ COMMITTED)
        • 可重复读 (REPEATABLE READ)
        • 串行化读 (SERIALIZABLE)
      • 间隙锁(Gap Lock)
      • 临键锁(Next-key Locks)
      • 其他问题
        • 表锁,InnoDB和MyISAM的区别
    • 行锁的分析
      • 查看行锁信息
      • 查看系统库锁相关数据表
        • 1、查看事务
        • 2、查看锁
        • 3、查看锁等待
        • 4、释放锁
        • 5、死锁
      • 锁优化的建议

转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

尽量用单表查询,计算类型根据情况而定,数据量庞大情况下使用Java操作,尽量不要写复杂SQL。

简介

事务,在数据库中是一个不可分割的工作单位。在MySQL中,一个事务是由一组SQL语句组成的序列,这组SQL语句作为一个整体被执行,也就是说,要么整体执行成功,要么整体执行失败。我们在平时使用的数据库,都会并发的执行多个事务,而这些多事务就很有可能会并发对同一批数据进行CRUD操作,如果没对这些做好相应处理,就会导致脏写、脏读、不可重复读、幻读的奇奇怪怪的问题。

事务及ACID

事务处理能够保证数据的一致性、准确性。事务有4个特性,也就是我们常说的ACID。

  • 原子性(Atomicity):事务的操作是原子操作,简单说就是一个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间环节。如果事务在执行一半的时候失败了,就会进行回滚到事务开始的状态,就相当于没执行过。
  • 一致性(Consistency):在事务开始和完成时,数据必须处于一致状态。
  • 隔离性(Isolation):数据库系统提供了隔离机制,每个事务能够独立执行,不被其他事务所干扰。
  • 持久性(Durability):一旦事务完成,则其结果能够永久保存在数据库中。即使发生系统崩溃,结果也不应该受到影响。

并发事务带来的问题

在并发事务的情况下,将会带来一些问题,接下来看一下将带来的问题。

丢失修改(Lost Modify)或脏写

当两个或者多个事务对同一行记录进行修改的时候,然后基于原始选择同时更新这一行时,可能会覆盖彼此的更新。例如,A事务和B事务同时获取同行数据(money=10),接着A事务扣掉5,B事务扣掉1,按道理最终结果要等于4,但是由于并发可能导致最后的结果不正确。

脏读(Dirty reads)

一个事务正在对一条记录进行修改,在这个事务完成并提交前,另一个事务也访问了这条记录。如果第二个事务读取了这个"脏"记录,那么可能产生问题,因为这个记录可能被回滚到开始的状态。例如,事务A读取库存信息,正在执行扣减库存,但是未提交;而事务B读到了事务A扣减的数据,然后进行修改数据,但是事务A回滚了,这就会导致数据错误了。

不可重复读(Non-repeatable reads)

在一个事务内,多次读取同一数据。在这个事务还没有结束时,另一个事务也访问了该数据。由于可能同时修改同一数据,使得第一个事务两次读取到的数据可能不致。也就是事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性。

幻读(Phantom reads)

两次读取范围内的记录,但是第二次读到了第一次没有读到的记录,这种现象称为"幻读”。也就是事务A读到了事务B提交的新增数据,不符合隔离性。

事务的隔离级别

对于“脏读”、“不可重复读”、“幻读”这些都是数据库读一致性的问题,需要通过数据库事务隔离级别机制来解决。
我们可以通过以下命令查看当前数据库的隔离级别

SHOW VARIABLES LIKE 'transaction_isolation';

在这里插入图片描述

在没有修改过数据库的隔离级别,默认就是REPEATABLE-READ,可重复读。
我们可以通过set命令来设置MySQL的事务隔离级别,一般是不建议修改MySQL的默认事务级别。

SET transaction_isolation = 'repeatable-read'

在spring程序中,如果没有设置隔离级别,那就是使用MySQL的默认隔离级别,否则使用spring中设置的隔离级别。
我们通过一张表格来直观的观察隔离级别与其能解决的问题。

隔离级别脏读
(Dirty Read)
不可重复读
(Non-repeatable Reads)
幻读
(Phantom Reads)
读未提交
(READ UNCOMMITTED)
未解决未解决未解决
读已提交
(READ COMMITTED)
解决未解决未解决
可重复读
(REPEATABLE READ)
解决解决未解决
串行化
(SERIALIZABLE)
解决解决解决

锁机制

锁是计算机来协调多个进程或线程并发访问某一资源的机制。
在数据库中,数据资源也是一种共享访问的资源,如何确保数据并发访问一致性、有效性是数据库需要解决的一大问题,锁冲突也是并发访问性能的一个重要因素。

锁分类

1)、从性能上又分为乐观锁(用版本号进行比对)和悲观锁
2)、从数据库操作类型来看有读锁写锁(都属于悲观锁)

  • 共享锁(Shared Lock,S锁):也就是读锁,如果一个事务T对数据A加上S锁,则只允许其他事务对数据A加S锁,不允许加X锁,直到T释放A上的S锁。这样可以保证其他事务可以读A,但是不能修改A。
  • 排他锁(Exclusive Lock,X锁):也就是写锁,如果一个事务T对数据A加上X锁,则其他事务不能再对A加任何锁,直到T释放A上的X锁。这样可以保证其他事务既不能读也不能写A。

3)、从锁的细粒度又分为行级锁定表级锁定
这是MySQL内部使用一种名为多版本并发控制(MVCC)的机制实现了高效的锁定策略。

  • 行级锁定:这是最小化的锁定规模,它使数据库可以极高效地对多用户访问进行管理。开销大、加锁慢,会出现死锁,发生所冲突的概率最低,并发度最高。
  • 表级锁定:对整个表进行加锁,开销比较小,加锁快,无死锁。但是并发性差,涉及表的所有查询都会被阻塞。

表锁

这是最大化的锁定规模,对整个表进行加锁,开销比较小,加锁快,无死锁。但是并发性差,涉及表的所有查询都会被阻塞。一般来说,表锁的使用是在整表的数据迁移的场景,当然,在使用FOR UPDATE也会导致表锁,从而可能会存在问题。

DROP TABLE IF EXISTS `employees`;
CREATE TABLE `employees`  (
  `employee_id` int(0) NOT NULL,
  `first_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `salary` decimal(10, 2) NULL DEFAULT NULL,
  `create_time` date NULL DEFAULT NULL,
  PRIMARY KEY (`employee_id`) USING BTREE,
  INDEX `idx_first_name_last_name_salary`(`first_name`, `last_name`, `salary`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `employees` VALUES (1, 'John', 'Doe', 73744.37, '2023-01-06');
INSERT INTO `employees` VALUES (2, 'Jane', 'Smith', 66799.74, '2023-02-22');
INSERT INTO `employees` VALUES (3, 'Bob', 'Johnson', 55495.71, '2023-11-21');
INSERT INTO `employees` VALUES (4, 'Alice', 'Williams', 53220.90, '2023-11-18');
INSERT INTO `employees` VALUES (5, 'Charlie', 'Brown', 61735.74, '2023-01-19');
INSERT INTO `employees` VALUES (6, 'Eva', 'Miller', 93990.88, '2023-04-27');
案例分析

首先准备了一张表来演示手动锁表,可以通过Navicat工具来测试。

LOCK TABLE 表名1 WRITE(READ), 表名2 WRITE(READ);

需要加读/写锁,通过write或者read指定就行。
通过SHOW OPEN TABLES;来查看表的加锁信息。
在这里插入图片描述

通过UNLOCK TABLES;就可以删除表锁。
以下来分析两种的特点:
1)、读锁: LOCK TABLE employees READ

加了读锁,当前的session和其他session都能够读取表的数据
当前的session去插入和更新数据,会导致失败。而其他的session会进行等待。

在这里插入图片描述

如以上案例,我在Navicat开启了两个会话,会话1对employees表加了全表读锁,在进行更新的时候,直接报错了,而会话2更新的时候会一直处于等待状态(tab显示正在处理),只有等锁被释放了,才能继续执行,这需要考虑锁的持续时间。
2)、写锁: LOCK TABLE employees WRITE

加了写锁,会导致当前session对加锁的表进行CRUD是允许的,而其他会话进行操作就会阻塞。

在这里插入图片描述

如以上案例,会话1更新成功,会话2被阻塞了。

行锁

最小化的锁定规模,开销大、加锁慢,会出现死锁,发生所冲突的概率最低,并发度最高。也是我们开发常使用到的一种锁类型。

案例分析

通过Navicat开启两个会话进行测试。
首先,在会话1开启事务,使用BEGIN命令。
然后执行更新语句UPDATE employees SET last_name = 'liyongde3' WHERE first_name = 'Jane';,此时并不提交事务。
然后我在新的会话去更新,先更新其他行数据,发现数据更新是正常的。
在这里插入图片描述

我们接着更新会话1更新的那条记录。就会发现会话2更新的时候被阻塞了。
在这里插入图片描述

只有将会话1的事务提交了,才能够继续执行更新。如果超过时间就会导致锁超时。
在这里插入图片描述

在这里插入图片描述

一个session开启了事务,更新不提交,在其他session更新同一条数据就会阻塞,更新其他数据不会。
注:读锁会阻塞写,但不会阻塞读。而写锁会把读写都阻塞。

行锁与事务隔离机制案例

这是最低的隔离级别。在这个级别,一个事务可以看见另一个未提交事务的修改(这就是所谓的“脏读”)。是能够可重复读,也会出现幻读。

接下来就来对事务的隔离机制进行案例分析。为了方便演示,接下来的测试就采用命令行窗口来进行,当然使用navicat也是可以的。操作的表依然是以上使用的employees表。

读未提交 (READ UNCOMMITTED)

首先将两个客户端设置事务隔离级别SET transaction_isolation = 'READ-UNCOMMITTED',并开启事务。
在这里插入图片描述

这样我们就得到了AB两个事务,一开始A事务查出John的salary=7344.37,事务B执行了扣掉200的操作,但是并没有提交,事务A随后查询发现了事务B没提交的数据。这就是读未提交。
在这里插入图片描述

当事务B回滚,那么事务A读取到事务B修改没提交的数据就成了"脏数据"了,这个数据就是无效的。那么当事务A进行执行扣除salary500,最后输出的结果会是73244.37。
在这里插入图片描述

然而这种情况是为什么呢?原因是因为这里采用的是salary = salary - 500。实际上在扣除数据的时候,此时的salary是从数据库获取的真实数据。

这里也就是我们需要注意的问题,如果salary-500是在Java层面操作,就会导致扣除的数据是错误数据。就正如以上数据,如果是在事务B回滚前获取的salary是73544.37,如果通过Java扣除再去赋值,那么最终的值将会是73044.37,这样就会导致数据的错误。所以在一般情况,像扣除数据最好是在SQL上去执行。

读已提交 (READ COMMITTED)

在这个级别,一个事务只能看到其他事务已经提交的修改。这个级别避免了“脏读”的发生,但还是会发生“不可重复读”和“幻影读”。
设置好事务隔离级别,分别开启事务。
我们在事务B进行-200的操作,但是并不提交,在事务A进行查询发现是查不到事务B刚修改的数据。这样就能够有效的解决了脏读的问题。
在这里插入图片描述

当事务B提交之后,事务A就读到了修改的数据。虽然解决了脏读,但是这个隔离级别依然是能够可重复读(同事务下两次读取的数据不一致)。
在这里插入图片描述

可重复读 (REPEATABLE READ)

MySQL的默认隔离级别。在这个级别,除了防止“脏读”,还防止了“不可重复读”,即在同一个事务内,多次读取同样的数据结果是一样的。但是,这个级别可能会产生“幻影读”。
继续以上例子,提交完设置可重复读的隔离机制,并开启事务。
如下截图,当事务B进行修改数据,未提交,事务A就看不到数据,直到事务B提交了,事务A查询也依然不会查到更新的数据。这个隔离级别下,不仅解决了脏读的问题,还解决了不可重复读的问题。
在这里插入图片描述

接着,当我们在事务A中,进行salary-500,那么结果并不是将73044.37去扣除的,而是将原来事务B扣掉的数据进行扣除。
在这里插入图片描述

可重复读的隔离级别使用了MVCC(multi-version concurrency control)机制,select基本是快照读(历史版本)。update、insert、delete才会更新版本号,是当前读(当前版本)。
如果是使用Java去扣除的话,就需要在读的时候加上锁,这样就能确保事务在修改数据的时候,防止其他事务同时修改。

MVCC,全称为多版本并发控制(Multi-Version Concurrency Control)。MVCC是一种用于解决数据库并发读写问题的技术,在MySQL的InnoDB引擎中就采用了MVCC来实现事务并解决读写冲突问题。在这个机制下,每个读操作都不会被其他的写操作阻塞,反之亦然。这意味着在读取数据的时候,不需要进行加锁操作,从而可以提高数据库的并发访问性能。这种机制主要是适用于读操作远多于写操作的系统中。

虽然能够解决脏读和不可重复读问题,但是还是不能解决幻读问题,接下来就来演示在这个隔离机制下的幻读情况。
在这里插入图片描述

当事务A读取不到客户端B插入的数据,但是,我们在事务A中进行修改id=12的值。我们发现事务A能够修改id=12的数据。这就是幻读。
在这里插入图片描述

这里我们注意一下,在可重复读的隔离级别下,查询是不会加锁的。
在这里插入图片描述

串行化读 (SERIALIZABLE)

这是最高的隔离级别,它会对所有的读取加锁,把事务强制变成串行执行,解决了所有的读一致性问题。不过因为所有事务都是串行执行的,所以效率会比较低。

与可重复读有重要的区别,读的时候,串行化会加锁,而可重复读是不会。

在这里插入图片描述

如以上截图,在串行化事务隔离级别中,查出多少行记录,将会锁住多少行,而如果查出是整表的数据,将会锁表。此时事务B(左边事务A,右边事务B)就没办法插入和对记录进行修改。如果事务A根据条件查询,那么条件筛选几条就锁几条。
我们来看看串行化是如何解决幻读的,因为串行化读会将查询/修改/插入的数据进行上锁,当我们在其他事务进行插入的时候,如果没有提交,那么另一个事务是没办法读取到那行记录。只有等事务提交之后,其他事务才能读到记录。
在这里插入图片描述

间隙锁(Gap Lock)

间隙锁(Gap Lock),是InnoDB存储引擎的一个重要特性,主要解决了幻读(Phantom Read)的问题。
只在可重复读的隔离级别中才能生效。

间隙锁和行锁一起,组成了InnoDB的两种锁定机制。行锁用于锁定数据记录,而间隙锁用于锁定范围,防止其他事务在该范围内插入新的记录。
总的来说就是会将范围内的记录锁住,无法修改;范围内的间隙锁住,无法新增。

image.png
如以上表格的数据,我们以id为例,(3,6)、(12,16)、(16,正无穷)分别有这几个区间,这些区间就是间隙。
在这里插入图片描述

在上面的例子中,执行的 UPDATE 语句是在一个事务中,意味着MySQL会对满足条件 employees_id > 4 and employees_id < 13 的记录加上行锁。具体而言,employee_id 为6, 7, 8, 9, 10, 11, 12的记录会被锁住。同时,InnoDB存储引擎还会采取使用间隙锁(Gap Locks)。表数据的间隙分别落在(3,6)和(12,16)这意味着它不仅会锁定满足条件的记录行,也会锁定条件覆盖的范围内索引间的“间隙”。也就是说,它将会锁住 employee_id 为4和employee_id 为13之间的间隙。
在这里插入图片描述

再来看这个例子,UPDATE语句的间隙会落在(3,6)和(12,16)以及(16,无穷大),所以整张表都会被锁住,无法被修改,而间隙会无法被插入。

临键锁(Next-key Locks)

临键锁(Next-key Lock)是InnoDB存储引擎用于解决幻读问题的lock机制,它其实是行锁和间隙锁的结合。

其他问题

这个是一个需要注意的点,锁主要是加在索引上,如果使用行锁不是加在索引上,行锁很可能会升级为表锁。
当session1执行update employees set salary = 1111 where first_name = ‘lyd’,如果没有加上索引,在session2对该表进行操作都会被阻塞。

Innodb的行锁是对索引加的锁,并不是针对记录加锁。如果索引没创建或者失效,就很可能导致表锁。

在MySQL中,锁住一行数据还有共享锁(Shared locks)排它锁(Exclusive locks)
共享锁又称为读锁,它允许一个事务来读取一行数据。如果一个事务对一行数据加了共享锁之后,其他事务还是可以对同一行数据加共享锁,也就是说它们可以共享,一起读取这行数据。但是在共享锁存在的时候,其他任何事务都不能对这行数据加排他锁,也就不能对这行数据进行修改或删除。在MySQL中,我们可以用“LOCK IN SHARE MODE”来对选定的数据添加共享锁。

SELECT * FROM employees WHERE employee_id = 6 LOCK IN SHARE MODE;

排他锁又称为写锁,当一个事务持有了一行数据的排他锁之后,其他任何事务都不能对这行数据加任何类型的锁。这就确保了该事务可以独占地修改或删除这行数据。我们可以用“FOR UPDATE”来对选定的数据添加排他锁(要注意添加索引,防止表锁)。

SELECT * FROM employees WHERE employee_id = 6 FOR UPDATE;
表锁,InnoDB和MyISAM的区别

MyISAM

MyISAM存储引擎仅支持表级锁定,不支持事务和行级锁定。主要有以下特点:
锁定级别较粗:由于MyISAM仅支持表级锁定,这意味着在对数据进行修改(包括增删改)的操作时,必须锁定完整的表,这可能会对并发性能造成影响。
读写冲突:在MyISAM中,读锁和写锁是互斥的,这意味着在写操作进行的过程中是不允许读取的,同样地,读取的过程中也不允许写入。
不支持事务:MyISAM不支持事务,也就无法进行回滚操作。

InnoDB

InnoDB存储引擎支持事务和行级锁定,以及通过其MVCC对读操作加锁,从而提高多用户并发性能。主要有以下特点:

  • 锁定级别更细:InnoDB支持行级锁定,这可以使得并发操作只锁定影响的那部分数据,而不是全部表数据,大大提高了并发性能。
  • 读写分离:InnoDB实现了读写分离,即使在写操作进行的过程中,也可以进行读取,不会因为写操作而阻塞读操作。
  • 支持事务和回滚:InnoDB支持事务,且每一个新变动都会先被保存在一个专用空间里(redo log),即使数据库崩溃也可以通过数据重建恢复。

行锁的分析

查看行锁信息

在MySQL中,SHOW STATUS LIKE 'innodb_row_lock%';用于查看有关InnoDB行锁的信息。
image.png
其中显示的值如下:

  • Innodb_row_lock_current_waits:当前正在等待获取锁的请求数目。
  • Innodb_row_lock_time:所有等待锁的操作所累积的时间(以毫秒为单位)。
  • Innodb_row_lock_time_avg:所有等待的操作的平均花费时间(以毫秒为单位)。
  • Innodb_row_lock_time_max:从开始以来单个等待操作的最长时间(以毫秒为单位)。
  • Innodb_row_lock_waits:从数据库启动开始,有多少次操作等待了锁定。

查看系统库锁相关数据表

MySQL8.0中,有information_schema和performance_schema两张系统的数据库,在遇到异常情况,可以通过这些表中查看锁、事务相关的信息。可以结合一些命令来查看哪些事务锁等待,在那张表那条SQL语句,有助于开发者排查错误。以下就是简单过一下。

1、查看事务

使用SELECT * FROM information_schema.INNODB_TRX;可以查看MySQL的事务。
image.png
我们可以通过navicat去查看表中有哪些字段。
image.png
关于更多的字段含义可以查看官方网站:MySQL官方文档

也可以看看网上的博客:

MySQL系统表information_schema.INNODB_TRX详解及查看当前运行事务_select * from information_schema.innodb_trx-CSDN博客

2、查看锁

通过SELECT * FROM performance_schema.data_locks;语句来查看MySQL8.0的所有的锁事务。
image.png

3、查看锁等待

通过SELECT * FROM performance_schema.data_lock_waits;可以查看锁的等待,这里,我模拟了一个锁等待事件,可看如下执行结果。
在这里插入图片描述

4、释放锁

kill tex_mysql_thread_id;释放锁需要找到事务中MySQL的线程id,这可以在information_schema.INNODB_TRX中查找。

5、死锁

在MySQL中,可以通过以下两种方式来获取关于死锁的信息:
1. SHOW ENGINE INNODB STATUS\G;命令:
这个命令会输出一些信息,其中包括最近一次死锁发生的详细信息。你可以看到被回滚的事务和相关的SQL语句。如下例子:

mysql> SHOW ENGINE INNODB STATUS\G;
*************************** 1. row ***************************
  Type: InnoDB
  Name:
Status:
=====================================
2024-02-02 22:36:56 0x4cd0 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 5 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 3 srv_active, 0 srv_shutdown, 14046 srv_idle
srv_master_thread log flush and writes: 0
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 74
OS WAIT ARRAY INFO: signal count 72
RW-shared spins 0, rounds 0, OS waits 0
RW-excl spins 0, rounds 0, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 0.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 129045
Purge done for trx's n:o < 129041 undo n:o < 0 state: running but idle
History list length 2
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 283982276143656, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283982276141328, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283982276140552, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283982276139776, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283982276139000, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283982276138224, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 129039, ACTIVE 2147 sec
4 lock struct(s), heap size 1128, 6 row lock(s), undo log entries 4
MySQL thread id 12, OS thread handle 19584, query id 148 localhost ::1 root
Trx read view will not see trx with id >= 129039, sees < 129039
--------
FILE I/O
--------
I/O thread 0 state: wait Windows aio (insert buffer thread)
I/O thread 1 state: wait Windows aio (log thread)
I/O thread 2 state: wait Windows aio (read thread)
I/O thread 3 state: wait Windows aio (read thread)
I/O thread 4 state: wait Windows aio (read thread)
I/O thread 5 state: wait Windows aio (read thread)
I/O thread 6 state: wait Windows aio (write thread)
I/O thread 7 state: wait Windows aio (write thread)
I/O thread 8 state: wait Windows aio (write thread)
I/O thread 9 state: wait Windows aio (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
1170 OS file reads, 450 OS file writes, 90 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 2 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 6 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 2 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 2 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number          1636447839
Log buffer assigned up to    1636447839
Log buffer completed up to   1636447839
Log written up to            1636447839
Log flushed up to            1636447839
Added dirty pages up to      1636447839
Pages flushed up to          1636447839
Last checkpoint at           1636447839
Log minimum file id is       499
Log maximum file id is       499
33 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 0
Dictionary memory allocated 532703
Buffer pool size   8191
Free buffers       6887
Database pages     1290
Old database pages 496
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 1, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 1146, created 144, written 221
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1290, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
1 read views open inside InnoDB
Process ID=5364, Main thread ID=5784 , state=sleeping
Number of rows inserted 0, updated 4, deleted 0, read 17
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
Number of system rows inserted 8, updated 331, deleted 8, read 20749
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================

1 row in set (0.00 sec)

ERROR:
No query specified

当排查死锁等案例时候,可以通过上面的日志协同排查。
2. 通过配置innodb_print_all_deadlocks变量:
可以将这个变量设置为ON,那么每当发生死锁时,MySQL都会在错误日志中打印死锁的详细信息:

SET GLOBAL innodb_print_all_deadlocks = ON;

锁优化的建议

  • 尽可能的让数据的检索通过索引来完成,这样可以避免无索引从行锁升级到表锁。
  • 设计索引要合理,尽量让索引锁住的行数达到最小。
  • 尽可能减小范围索引,可以有效控制间隙锁。
  • 在满足业务需求的前提下,尽量选择更小的锁粒度(行锁代替表锁)
  • 通过设定合适的事务隔离级别来控制并发事务的行为。这需要对各个隔离级别的行为有深入的理解。
  • *减少等待锁的时间可以减少死锁的可能性。设计时要考虑让事务尽可能快地提交。(这个在开发中经常遇到,需要注意)

注:以上涉及的SQL部分在MySQL5.7之前的版本和MySQL8.0会有写不一样,本文采用的是MySQL8.0版本的,尽可能根据官方文档来。

👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍

转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[云顶数模]2024美赛CEF题成品参考论文+配套数据集+可执行代码+运行结果图

E题社区抗灾能力综合评估与决策模型研究 摘要&#xff1a;社区抗灾能力的提升对于灾害风险管理至关重要。本研究基于机器学 习方法&#xff0c;构建了社区抗灾能力预测模型&#xff0c;以评估社区在灾害事件中的表现。首先&#xff0c; 我们采用梯度提升树模型对社区基础设施、…

Enemy Rat(老鼠模型)

信息: - 模型有 1.491 个顶点。 - 纹理&#xff1a;颜色、法线、粗糙度、发射、金属、等级&#xff08;2048x2048 尺寸&#xff09; 下载&#xff1a; ​​Unity资源商店链接 资源下载链接 效果图&#xff1a;

NAS系统折腾记 – Emby搭建家庭多媒体服务器

Emby简介 Emby是一款优秀的媒体服务器软件&#xff0c;致力于为用户提供丰富的多媒体体验。通过Emby&#xff0c;您可以方便地在家庭内的各种设备上观看您喜爱的电影、电视剧和其他视频内容。而且&#xff0c;Emby还具备强大的媒体管理功能&#xff0c;让您的影视资源井然有序…

PSQL常用操作

目录 前言 准备工作 添加postgres用户 初始化数据库 启动服务 创建数据库 psql连接数据库 常规操作 数据库 schema相关 插件 其他 前言 老折腾&#xff0c;还是记录点啥吧...... 基于本地PG数据库(打包为绿色版本了)&#xff0c;实操记录&#xff0c;版本pgsql12…

大模型ReAct提示框架

Yao 等人于 2022 年引入了一个名为 ReAct 的框架&#xff0c;其中 LLM 用于以交错的方式生成推理轨迹&#xff08;reasoning traces&#xff09;和特定于任务的操作。 生成推理轨迹允许模型诱导、跟踪和更新行动计划&#xff0c;甚至处理异常。 操作步骤允许与外部源&#xff…

云尘 -- 铁三域控

描述&#xff1a; flag1 直接fscan开扫 发现存活两台机子123和141&#xff0c;其中141这台机子扫出来有ms17-010漏洞 继续信息收集&#xff0c;用nmap扫一波全端口&#xff0c;看看有没有遗漏 141这台机子一开始没扫到&#xff0c;看着提示使用-Pn再扫一遍就行了。因为如果当…

docker-学习-2

docker学习第二天 docker学习第二天1.docker和虚拟机的区别2.docker的底层隔离机制2.1 Namespaces(命名空间)2.1.1 什么是命名空间 2.2 Cgroups2.3 Union file systems2.4 Container format2.5 docker在底层如何做隔离的&#xff0c;如何进行资源限制的&#xff1f; 3. docker命…

ep-bg-purple-dark element-plus 不生效

element-plus 官网里面的 Layout 布局中的示例&#xff0c;官方文档中添加类名 class"grid-content ep-bg-purple-dark" 有相应的样式 import element-plus/theme-chalk/index.css //默认css样式 英文 import element-plus/dist/index.css 两…

【Leetcode】2670. 找出不同元素数目差数组

文章目录 题目思路代码结果 题目 题目链接 给你一个下标从 0 开始的数组 nums &#xff0c;数组长度为 n 。 nums 的 不同元素数目差 数组可以用一个长度为 n 的数组 diff 表示&#xff0c;其中 diff[i] 等于前缀 nums[0, …, i] 中不同元素的数目 减去 后缀 nums[i 1, …, …

在jetbrains IDEA/Pycharm/Android Studio中安装官方rust插件,开始rust编程

在idea插件市场搜索rust&#xff1a;JetBrains Marketplace &#xff0c;就可以找到rust插件&#xff1a; jetbrains官方rust插件地址&#xff1a;[Deprecated] Rust - IntelliJ IDEs Plugin | Marketplace 直接在idea中搜索rust好像是搜不到的&#xff1a; 需要在这个插件市场…

STL常用容器—list容器(链表)

STL常用容器—list容器&#xff08;链表&#xff09; 一、list容器基本概念二、list容器基本操作与常用方法1. list构造函数2. ☆list 插入和删除3. list 获取头尾数据4. list 大小操作5. list赋值和交换6. list 反转和排序 三、排序案例 参考博文1: &#xff1c;C&#xff1e;…

Cambalache in Ubuntu

文章目录 前言apt install flatpak这很ok后记 前言 gtkmm4相比gtkmm3有很多改革, 代码也干净了许多, 但在windows上开发 有ui设计器那自然方便很多, 但glade又不支持gtkmm4, windows上装Cambalache很是困难. 各种问题都找不到答案.于是 我用VMware虚拟机Ubuntu20.xx安装Cambal…

深度学习:数据驱动的人工智能革命

文章目录 每日一句正能量前言什么是深度学习推动AI发展不同阶段的“三大驱动 ”1、技术驱动&#xff1a;算法和计算力是主要驱动力2、计算力的三驾马车&#xff1a;芯片、超级计算机、云计算3、数据驱动&#xff1a;描绘个性化画像&#xff1b; 后记 每日一句正能量 一般青年的…

日志追踪-Tracing

1. 前言 分布式链路跟踪中有两个重要的概念&#xff1a;跟踪&#xff08;trace&#xff09;和 跨度&#xff08; span)。trace 是请求在分布式系统中的整个链路视图&#xff0c;span 则代表整个链路中不同服务内部的视图&#xff0c;span 组合在一起就是整个 trace 的视图在整个…

BUUCTF-Real-[struts2]s2-013

struts2的标签中 <s:a> 和 <s:url> 都有一个 includeParams 属性&#xff0c;可以设置成如下值none - URL中不包含任何参数&#xff08;默认&#xff09; get - 仅包含URL中的GET参数 all - 在URL中包含GET和POST参数 当includeParamsall的时候&#xff0c;会将本次…

学术研究新突破:发现新型相变存储器

斯坦福大学的研究人员开发出了一种新型相变存储器&#xff0c;该存储器有望帮助计算机更快、更高效地处理大量数据。在最近发表于《自然通讯》的一篇论文中&#xff0c;研究人员详细介绍了这项技术&#xff0c;表明一种新材料可能会使基于电阻高低状态切换以创建计算机数据“0”…

2024美赛数学建模D题思路+代码

文章目录 1 赛题思路2 美赛比赛日期和时间3 赛题类型4 美赛常见数模问题5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 美赛比赛日期和时间 比赛开始时间&#xff1a;北京时间2024年2月2日&#xff08;周五&#xff…

Blender教程(基础)-面的尖分、三角化与融并-09

一.面的尖分 1.准备 新建如下图所示物体、切换到编辑模式下 2.右键尖分正方形面 在选择中的面上右键选择尖分面 效果如下所示 3.右键尖分圆形面 效果如下 可以自行调节参数 二.面的三角化 1、正方形 2、圆形 三.融并 1、尖分圆形面 2、尖分圆形面-融并 发现…

Unity Meta Quest MR 开发(三):Scene API 配置+实现虚拟与现实之间的碰撞

文章目录 &#x1f4d5;教程说明&#x1f4d5; Scene 配置⭐开启场景理解功能和应用访问空间数据的权限⭐OVRSceneManager⭐制作 Plane Prefab 和 Volume Prefab⭐运行场景⭐添加透视材质 &#x1f4d5;虚拟与现实物体的碰撞&#xff08;弹球 Demo&#xff09;&#x1f4d5;Mes…

两数之和 - 暴力枚举+哈希表

两数之和原题地址 方法一&#xff1a;暴力枚举 首先&#xff0c;我们需要枚举数组中所有可能的下标对组合&#xff0c;对于n个数的数组&#xff0c;从中选2个下标&#xff0c;有种可能。做法很简单&#xff0c;遍历数组中的所有元素&#xff0c;对于每一个元素&#xff0c;遍…