上图2张图,可以看到延迟较大,从库上的alter操作一直在等待metadata lock,处于阻塞状态。
数据库的监控点中,阻塞情况是一个重要指标,Innodb 是主流存储引擎,下面实验一下如何监控器阻塞状态 模拟阻塞状态 使用两个MySQL客户端连接同一个MySQL服务器,并查询出各自的连接ID client1 的 ID为 5 client2 的 ID为 6 先把阻塞过期时间设得大一点,便于测试 mysql> set global innodb_lock_wait_timeout=200; 在 client1 中执行语句 mysql> begin; mysql> select film_id from film for update; 可以正常返回数据 在 client2 中执行语句 mysql> begin ; mysql> select title from film for update; 没有返回结果,处于等待状态,因为被阻塞了,完成了模拟 查询阻塞 执行下面的语句来查询阻塞 select b.trx_mysql_thread_id as '被阻塞线程' ,b.trx_query as '被阻塞SQL' ,c.trx_mysql_thread_id as '阻塞线程' ,c.trx_query as '阻塞SQL' ,(UNIX_TIMESTAMP
出现的错误: ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 解决办法: 查看sleep的进程 MySQL mysql> SELECT * FROM information_schema.INNODB_TRX\G; *************************** 1. row ************ trx_requested_lock_id: NULL trx_wait_started: NULL trx_weight: 4 trx_mysql_thread_id sec) ERROR: No query specified 看到有这条 32735 的sql,kill掉,执行kill 32735; kill 32735; 然后再去查询INNODB_TRX表,就没有阻塞的事务 sleep线程存在了,如下所示: mysql> SELECT * FROM information_schema.INNODB_TRX\G; Empty set (0.00 sec) 现在可以正常执行
在 MySQL 数据库的日常管理和优化中,进程管理是一项重要的任务。通过监控和适时地终止异常或低效的数据库连接和查询,可以显著提升系统的性能和稳定性。 下面介绍几种常见的 MySQL 进程管理场景及相应的处理策略。 每隔多久检查一次 --victims all #all kill该类中所有的查询;oldest 只kill最旧的单个查询;all-but-oldest 除了就得查询外,其他的都kill 总结 通过对 MySQL
在Java并发包中提供了两种类型的队列,非阻塞队列与阻塞队列,当然它们都是线程安全的,无需担心在多线程并发环境所带来的不可预知的问题。为什么会有非阻塞和阻塞之分呢? 这里的非阻塞与阻塞在于有界与否,也就是在初始化时有没有给它一个默认的容量大小,对于阻塞有界队列来讲,如果队列满了的话,则任何线程都会阻塞不能进行入队操作,反之队列为空的话,则任何线程都不能进行出队操作。 非阻塞队列:ConcurrentLinkedQueue 阻塞队列:ArrayBlockingQueue、LinkedBlockingQueue、…… 本文介绍非阻塞队列——ConcurentLinkedQueue tail, p = t;;) { 7 Node<E> q = p.next; 8 if (q == null) { //此时p指向的就是队列真正的尾节点 9 = h) 9 updateHead(h, ((q = p.next) != null) ?
某银行客户在从Oracle迁移到MySQL的开发中,MySQL在READ-COMMITTED隔离级别下,出现了insert阻塞update的情况,但同样的情况下,Oracle的insert则不会阻塞update (0.01 sec) 更改数据,条件是a=8,将会被阻塞mysql> update t set b=0 where a=8;<<挂起,等待innodb_lock_wait_timeout超时 2 说明:被阻塞事务执行的sql语句update t set b=0 where a=8, 阻塞事务执行的sql语句是insert into t values(8,8)。 (Oracle也同样阻塞)。 Oracle中insert没有阻塞update 在Oracle中,创建同样的测试表t,执行同样的insert和update,但insert不会阻塞update。
要确保mysql 数据库的 datadir是清空的,否则会报错 [root@slave02 data]# cat restore.log nohup: ignoring input Warning: /usr/bin/innobackupex version 2.3.2 based on MySQL server 5.6.24 Linux (x86_64) (revision id: 306a2e0 ) Original data directory /var/lib/mysql is not empty! ) Original data directory /var/lib/mysql is not empty! 开头的文件 如: .bash_history .lesshst .mysql_history .viminfo 要指明删,如 rm -rf .bash_history .lesshst .mysql_history
要确保mysql 数据库的 datadir是清空的,否则会报错 [root@slave02 data]# cat restore.log nohup: ignoring input Warning: /usr/bin/innobackupex version 2.3.2 based on MySQL server 5.6.24 Linux (x86_64) (revision id: 306a2e0 ) Original data directory /var/lib/mysql is not empty! ) Original data directory /var/lib/mysql is not empty! 开头的文件 如: .bash_history .lesshst .mysql_history .viminfo 要指明删,如 rm -rf .bash_history .lesshst .mysql_history
这是一套MySQL 5.7.16的环境,事务隔离级别为RR 等我连接到这套环境的时候,show processlist的输出已经恢复了正常,查看相关的数据库日志也没有任何额外的输出,查看慢日志发现了有一部分的慢日志 业务服务器会不断发起短连接请求,整个过程中是无状态的,发起的数据写入很可能是冗余的,为了在数据库中达到唯一性,设置了这个唯一性索引,而业务的持续不断的写入,因为唯一性索引会额外有检测数据库冲突的逻辑,所以相关的SQL都会阻塞
2.知识 性能优化是通过合理安排资源,调整MySQL参数,服务器环境等手段使得MySQL 运行更快,更节省资源。 常见的优化方法: 查询优化 数据库表结构设计优化 MySQL所在的服务器优化 可以从多个方面进行性能优化,原则是 尽量减少系统的瓶颈,减少资源的占用,加快系统的响应速度。 比如: 优化系统的文件系统,以提高磁盘I/O的读写速度; 优化操作系统调度策略,以提高MySQL在高负荷情况下的负载能力; 优化表结构,索引,查询语句使得查询的响应更快。 它虽然很灵活,但执行效率不高,MySQL 需要未内层查询语句的查询结果建立一个临时表,然后外层的查询语句从临时表里再次查询。查询完毕后,销毁这些临时表。 优化 MySQL 服务器 硬件优化 配置较大内存 配置高速磁盘 合理分布磁盘I/O 多处理器等 优化MySQL配置文件的参数 MySQL配置参数在my.cnf , my.ini 文件中,根据经验修改参数达到优化目的
MySQL DDL操作执行的三种方式 1,INPLACE,在进行DDL操作时,不影响表的读&写,可以正常执行表上的DML操作,避免与COPY方法相关的磁盘I/O和CPU周期,从而最小化数据库的总体负载。 过程是通过创建一个新结构的临时表,将数据copy到临时表,完成后删除原表,重命名新表的方式,需要拷贝原始表, 3,INSTANT,从 MySQL 8.0.12 开始被引入并默认使用。 以下是MySQL 5.7版本中各种DDL操作的执行方式,总结一下: 1,如果DDL的执行方式是InPlace = YES ,那么改DDL的执行会支持并发DML,不会影响表的增删查改, 1.1,如果 Only Modifies Metadata一定为No,需要考虑Rebuilds Table对IO和CPU等资源的消耗 2,如果DDL的执行方式是InPlace = NO,那么改DDL的执行期间表只读,阻塞写
阻塞与非阻塞 应用进程请求I/O操作时,如果数据未准备好,如果请求立即返回就是非阻塞,不立即返回就是阻塞。简单说就是做一件事如果不能立即获得返回,需要等待,就是阻塞,否则就可以理解为非阻塞。 阻塞 阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上它们是不同的。 socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。 非阻塞 非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。 同步/异步与阻塞/非阻塞的组合 同步阻塞形式: 等待执行结果是一直等待,执行时线程挂起(未对fd 设置O_NONBLOCK 标志位的read/write 操作) 同步非阻塞形式:等待执行结果是一直等待,
mysql的事务默认是自动提交的,也就是说,当执行一条DML语句,Mysql会立即隐式的提交事务 二、事务操作 2.1 查看事务提交方式 select@@autocommit; 2.2 设置事务提交方式 | serializable}; 说明1:session :设置仅对当前对话起作用 说明2:global :设置对全局都有用 六、事务的演示 6.1 案例使用的accout表结构及数据 mysql 在进行异常展示之前,先把数据恢复成各自2000的余额 mysql> update account set money=2000; Query OK, 2 rows affected (0.02 sec) Rows matched: 2 Changed: 2 Warnings: 0 mysql> select * from account; +----+--------+-------+ | id 6.4 案例3 使用事务完成,首先同样也是先还原数据,每个人的余额都是2000元 mysql> select * from account; +----+--------+-------+ |
什么是阻塞和非阻塞 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。 阻塞与非阻塞:针对函数(程序)运行的方式,在IO未就绪时,是等待就绪还是直接返回(执行别的操作)。 阻塞与非阻塞的区别: 阻塞是程序在调用系统函数IO时,在系统执行系统调用时由CPU通过轮询等方式来实现数据的IO。 非阻塞是在程序级别通过轮询/信号/事件的机制,去查看IO数据是否就绪。 可以是阻塞或非阻塞,阻塞则一直在等待内核/应用程序把IO数据准备好,非阻塞则是直接返回内核/应用程序是否已经准备好数据。 应用程序框架:同步或异步。 IO多路复用,同步,异步,阻塞和非阻塞 区别 关于异步,同步,阻塞与非阻塞 解读I/O多路复用技术
以调用函数为例, 同步指的是调用方主动查询返回结果,异步是等待被调用方通知查询结果 阻塞是等待返回结果的时间内挂起,非阻塞是等待返回结果的时间内可以干其他事情. 同步和阻塞完全不是一件事,是否同步指的是获取返回结果的方式,是否阻塞指的是等待获取结果的时间内是否可以干其他事情
曾经我分析过在MySQL数据库上字段扩位是否只是快速更新元数据的那次是因为是在实际工作中意外遇到的问题,所以做了实验得出在64以下改变没有问题。64以上的改变也没有问题。 事实证明我判断正确的实际效果模拟一个100M以上的表mysql> select count(*) from test_data;+----------+| count(*) |+----------+| 1000000 |+----------+1 row in set (0.74 sec)mysql> desc test_data;+-------+---------------+------+- mysql> mysql> alter table test_data modify m varchar(50);Query OK, 0 rows affected (0.02 sec)Records: 这些后续可以更好的判断DDL时候的阻塞情况
二、分类 MySQL中的锁、按照锁的粒度分,分为以下三类 全局锁:锁定数据量的所有表 表级锁:每次操作锁住整张表 行级锁:每次操作锁住对应的行数据 三、全局锁 3.1 简介 全局锁就是对整个数据库实例枷锁 3.5 案例二 说明1:客户端1中设置了全局锁 说明2:客户端3中做了数据库备份的语句,其中mysqldump是和mysql一样由MySQL服务器提供的数据库备份的命令 说明3:当数据库设置了全局锁的时候,不影响数据库的备份 说明4:MySQL备份实在终端命令行模式下,不是在数据库命令模式下,注意! 说明3:当把锁释放了,自己及其他客户端的新增,删除和修改语句才会结束阻塞。 说明9:InnoDB的行锁是针对于索引加的锁,不通过索引检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁 说明10:根据业务需要,尽量使用索引当所查询条件,既快又减少阻塞
这里讲的都是基于IO的 阻塞、非阻塞、同步、异步 ---- 一个典型的IO操作包括了两个阶段,数据准备和数据读写。比如说现在要使用 recv 执行一个读操作,数据就绪就是远端是否有数据可读。 当IO工作在阻塞状态下的时候,如果数据没有就绪,recv就会阻塞当前线程;如果说IO工作在非阻塞状态下,会立即返回。 一个同步IO接口的示例: char buf[1024]; int sz = recv(sockfd,buf,1024,0); //阻塞:一直在这儿死等 //非阻塞:时不时的回来问一下 if(sz>0) 仅被 lio_listio() 函数使用 */ /* Various implementation-internal fields not shown */ }; 陈硕大神说:在处理IO的时候,阻塞和非阻塞都是同步 ---- 五种IO模型 阻塞: 非阻塞: 多路IO复用 信号驱动: 这里就完全放飞自我了 异步: ---- Reactor反应堆模型 One loop per thread
:”发送操作被阻塞了!!! 阻塞 阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上它们是不同的。 非阻塞 非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。 对象的阻塞模式和阻塞函数调用 对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。 阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。
我们可能都已经听过阻塞非阻塞的概念,本文以tcp中的connect系统调用为例子(基于1.12.13内核,新版的原理类似,但是过程就很复杂了,有时间再分析),分析阻塞和非阻塞是什么并且看他是如何实现的。 sock->state = SS_CONNECTED; // 返回成功 return(0); } 我们看到connect函数首先会调用tcp层的函数发送一个sync包,然后根据socket的属性(阻塞非阻塞 ,可以通过setsocketopt设置)做下一步处理,如果是非阻塞,那么就比较简单,直接返回给应用层。 这也是非阻塞+事件驱动架构中的做法。因为这种架构下通常是单进程的,要避免阻塞进程,那么返回后什么时候才能知道连接成功呢? 以上就是进程阻塞和非阻塞的原理。