本文主要是介绍mysql 事务与connection,锁,慢sql,如何解决,杀死执行的线程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前提说明
navicat中每打开一个窗口就是打开一个connection,关掉窗口就是关掉connection
事务与connection
测试事务不提交的情况
(步骤1)先打开一个窗口,开启一个事务T1插入一条数据,这里不进行提交。
由于在一个事务中,所以select 能立刻查出insert的但还没提交的数据。
查询是否开启 事务超时,回滚策略。
SHOW GLOBAL VARIABLES LIKE 'innodb_rollback_on_timeout';
若为off则表示不开启,事务会一直存在,此时只有当连接关闭时,才会回滚。
若为on,则表示开启,当事务超时时,会自动回滚。
查询当前connection的事务id
SELECT TRX_ID
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
(步骤2)再打开一个窗口,开启事务T2,并插入同样的id,会发现一直卡在那,等待id=3的锁释放。
由于事务T1一直没有提交,T2就一直等待锁释放,直到等待锁超时。
查询锁超时的sql:
SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout';
如何杀死mysql中的某些线程,如慢sql,锁,事务等
可查询 锁,事务等对应的执行线程,然后杀死
连接mysql,输入命令:
kill 线程id
事务相关-connection 和事务的关系,以及总结
在一个connection中
按步骤执行,第一、二、三步。可发现
(1)START TRANSACTION 会把当前connection中,前面的所有事务(其实,前面最多有一个事务,可参看2解释)都提交(就相当于commit作用)。
(2)一个connection 中一个时间段内,只能有一个活跃事务。
(3)connection 断开,事务就会回滚。
(4)若开启了事务执行超时时间,则事务超时,就会回滚。
#########第一步
START TRANSACTION;
insert into test3(id,name) values(4,'4');
#查询事务id,此时在其他事务中,查不到4
SELECT TRX_ID
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();###########第二步
START TRANSACTION;
#此时在其他事务中可查到id为4的数据
select * from test3;#可以查询到4,说明START TRANSACTION时会把以前没有commit的事务都commit。就相当与执行commit命令
insert into test3(id,name) values(5,'5');
#事务id和第一步不同
SELECT TRX_ID
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();##########第三步
insert into test3(id,name) values(6,'6');
#事务id和第二步一样,说明若不提交或回滚 则后面的sql会追加到前面的事务中。
#也就是一个connection中 在一个时间段,只能有一个事务活跃。
SELECT TRX_ID
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
#此时在其他事务中查不到id为5和6的数据
commit;
#此时在其他事务中可查到id为5和6的数据
事务相关操作
本人没有找到关于指定事务id的相关操作命令。。
#查询server中所有innodb中活跃的事务,可根据开始时间判断事务执行了多长时间,长事务
select * from information_schema.innodb_trx;
#根据线程id杀掉
kill 14331733;
#查询事务是否开启超时回滚,若为off,则只能等到connection断开才能回滚
SHOW GLOBAL VARIABLES LIKE 'innodb_rollback_on_timeout';
慢sql相关
参考mysql查看实时语句和慢sql | Chris Chan's BLOG
mysql 开启慢查询 清空slow_log日志或者slow_log表_zhonglijun_05的博客-CSDN博客_slow_log
#开启慢查询日志
set GLOBAL slow_query_log =1;
show VARIABLES like 'slow_query_log';#设置慢查询日志存储在文件中
set global log_output='FILE';
set GLOBAL slow_query_log_file='D:/temp/mysql/DB-Server-slow.log';#设置慢查询日志存储在表中,即mysql.slow_log
set global log_output='TABLE';
#查询log_output存储类型
show variables like '%log_output%';#设置sql执行多长时间,才记录到日志
set global long_query_time=4;#查询存储早表中的慢查询日志
select * from mysql.slow_log;
如果你想自己试试慢sql是否被记录,那么可以使用select sleep(5);
这样的语句,执行效果如下:
mysql> select sleep(5) ;
+----------+
| sleep(5) |
+----------+
| 0 |
+----------+
1 row in set (5.00 sec)mysql> select * from mysql.slow_log;
+---------------------+---------------------------+------------+-----------+-----------+---------------+----+----------------+-----------+-----------+-----------------+-----------+
| start_time | user_host | query_time | lock_time | rows_sent | rows_examined | db | last_insert_id | insert_id | server_id | sql_text | thread_id |
+---------------------+---------------------------+------------+-----------+-----------+---------------+----+----------------+-----------+-----------+-----------------+-----------+
| 2018-01-30 21:45:23 | root[root] @ localhost [] | 00:00:05 | 00:00:00 | 1 | 0 | | 0 | 0 | 1 | select sleep(5) | 2 |
+---------------------+---------------------------+------------+-----------+-----------+---------------+----+----------------+-----------+-----------+-----------------+-----------+
1 rows in set (0.00 sec)
查询记录中有thread_id字段。
但是本人测试,只有在执行完后,才会插入慢日志,才能查询到。
锁相关- 查询当前锁记录的线程 以及等待锁的线程
当前出现的锁
mysql> SELECT * FROM information_schema.INNODB_LOCKs;
锁等待的对应关系
mysql> SELECT * FROM information_schema.INNODB_LOCK_waits;
解释:看事务表INNODB_TRX,里面是否有正在锁定的事务线程,看看ID是否在show processlist里面的sleep线程中,如果是,就证明这个sleep的线程事务一直没有commit或者rollback而是卡住了,我们需要手动kill掉。
注意:innodb_locks表在8.0.13版本中由performance_schema.data_locks表所代替,innodb_lock_waits表则由performance_schema.data_lock_waits表代替。
原文链接:https://blog.csdn.net/dujianxiong/article/details/90770301
查询当前正在运行的线程
show processlist;
或者
select * from information_schema.processlist
可以看到sql 已经执行了多长时间,其中id就是线程id,可在mysql中,用kill 线程id进行杀死
各列的含义和用途:
ID列
一个标识,你要kill一个语句的时候很有用,用命令杀掉此查询 /*/mysqladmin kill 进程号。
user列
显示单前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。
host列
显示这个语句是从哪个ip的哪个端口上发出的。用于追踪出问题语句的用户。
db列
显示这个进程目前连接的是哪个数据库。
command列
显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。
time列
此这个状态持续的时间,单位是秒。
state列
显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个 sql语句,以查询为例,可能需要经过copying to tmp table,Sorting result,Sending data等状态才可以完成
info列
显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。
这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:
Checking table
正在检查数据表(这是自动的)。
Closing tables
正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
复制从服务器正在连接主服务器。
Copying to tmp table on disk
由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
正在创建临时表以存放部分查询结果。
deleting from main table
服务器正在执行多表删除中的第一部分,刚删除第一个表。
deleting from reference tables
服务器正在执行多表删除中的第二部分,正在删除其他表的记录。
Flushing tables
正在执行FLUSH TABLES,等待其他线程关闭数据表。
Killed
发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。
Locked
被其他查询锁住了。
Sending data
正在处理SELECT查询的记录,同时正在把结果发送给客户端。
Sorting for group
正在为GROUP BY做排序。
Sorting for order
正在为ORDER BY做排序。
Opening tables
这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLE或LOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。
Removing duplicates
正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
修复指令正在排序以创建索引。
Repair with keycache
修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。
Searching rows for update
正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。
Sleeping
正在等待客户端发送新请求.
System lock
正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。
Upgrading lock
INSERT DELAYED正在尝试取得一个锁表以插入新记录。
Updating
正在搜索匹配的记录,并且修改它们。
User Lock
正在等待GET_LOCK()。
Waiting for tables
该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。
waiting for handler insert
INSERT DELAYED已经处理完了所有待处理的插入操作,正在等待新的请求。
大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。
还有其他的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。
其他网上参考
Mysql 锁、事务强制手动kill/释放
1、查看数据库当前的进程,看一下有无正在执行的慢SQL记录线程。
mysql> show processlist;
2、查看当前的事务
注意:innodb_locks表在8.0.13版本中由performance_schema.data_locks表所代替,innodb_lock_waits表则由performance_schema.data_lock_waits表代替。
当前运行的所有事务
mysql> SELECT * FROM information_schema.INNODB_TRX;
当前出现的锁
mysql> SELECT * FROM information_schema.INNODB_LOCKs;
锁等待的对应关系
mysql> SELECT * FROM information_schema.INNODB_LOCK_waits;
解释:看事务表INNODB_TRX,里面是否有正在锁定的事务线程,看看ID是否在show processlist里面的sleep线程中,如果是,就证明这个sleep的线程事务一直没有commit或者rollback而是卡住了,我们需要手动kill掉。
搜索的结果是在事务表发现了很多任务,这时候最好都kill掉。
3、批量删除事务表中的事务
我这里用的方法是:通过information_schema.processlist表中的连接信息生成需要处理掉的MySQL连接的语句临时文件,然后执行临时文件中生成的指令。
mysql> select concat('KILL ',id,';') from information_schema.processlist p inner
join information_schema.INNODB_TRX x on p.id=x.trx_mysql_thread_id where db='test';
+------------------------+
| concat('KILL ',id,';') |
+------------------------+
| KILL 588379; |
| KILL 588313; |
| KILL 588275; |
+------------------------+
3 rows in set
kill掉以后再执行SELECT * FROM information_schema.INNODB_TRX; 就是空了。
这时候系统就正常了
原文链接:https://blog.csdn.net/dujianxiong/article/details/90770301
这篇关于mysql 事务与connection,锁,慢sql,如何解决,杀死执行的线程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!