mysql数据库表锁等待超时怎么解决当你开始执行一个 ALTER ,而你遇到了可怕的“元数据锁定等待” , 我敢肯定你一定遇见过 。我最近遇到了一个案例,其中被更改的表要执行一个很小范围的更新(100行) 。ALTER 在负载测试期间一直等待了几个小时 。在停止负载测试后,ALTER 按预期在不到一秒的时间内就完成了 。那么这里发生了什么?
检查外键
每当有奇数次锁定时,我的第一直觉就是检查外键 。当然这张表有一些外键引用了一个更繁忙的表 。但是这种行为似乎仍然很奇怪 。对表运行 ALTER 时,会针对子表请求一个 SHARED_UPGRADEABLE 元数据锁 。还有针对父级的 SHARED_READ_ONLY 元数据锁 。
我们来看看如何根据文档获取元数据锁定[1]:
如果给定锁定有多个服务器,则首先满足最高优先级锁定请求,并且与 max_write_lock_count系统变量有关 。写锁定请求的优先级高于读取锁定请求 。
[1]:
请务必注意锁定顺序是序列化的:语句逐个获取元数据锁,而不是同时获取 , 并在此过程中执行死锁检测 。
通常在考虑队列时考虑先进先出 。如果我发出以下三个语句(按此顺序),它们将按以下顺序完成:
1. INSERT INTO parent2. ALTER TABLE child3. INSERT INTO parent
但是当子 ALTER 语句请求对父进行读取锁定时,尽管排序,但两个插入将在 ALTER 之前完成 。以下是可以演示此示例的示例场景:
数据初始化:
CREATE TABLE `parent` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `child` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`val` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_parent` (`parent_id`),
CONSTRAINT `fk_parent` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB;
INSERT INTO `parent` VALUES (1, "one"), (2, "two"), (3, "three"), (4, "four");
Session 1:
start transaction;update parent set val = "four-new" where id = 4;
Session 2:
alter table child add index `idx_new` (val);
Session 3:
start transaction;update parent set val = "three-new" where id = 3;
此时,会话 1 具有打开的事务,并且处于休眠状态,并在父级上授予写入元数据锁定 。会话 2 具有在子级上授予的可升级(写入)锁定,并且正在等待父级的读取锁定 。最后会话 3 具有针对父级的授权写入锁定:
mysql select * from performance_schema.metadata_locks; ------------- ------------- ------------------- --------------- ------------- | OBJECT_TYPE | OBJECT_NAME | LOCK_TYPE| LOCK_DURATION | LOCK_STATUS | ------------- ------------- ------------------- --------------- ------------- | TABLE| child| SHARED_UPGRADABLE | TRANSACTION| GRANTED| - ALTER (S2)| TABLE| parent| SHARED_WRITE| TRANSACTION| GRANTED| - UPDATE (S1)| TABLE| parent| SHARED_WRITE| TRANSACTION| GRANTED| - UPDATE (S3)| TABLE| parent| SHARED_READ_ONLY| STATEMENT| PENDING| - ALTER (S2) ------------- ------------- ------------------- --------------- -------------
请注意,具有挂起锁定状态的唯一会话是会话 2(ALTER) 。会话 1 和会话 3 (分别在 ALTER 之前和之后发布)都被授予了写锁 。排序失败的地方是在会话 1 上发生提交的时候 。在考虑有序队列时,人们会期望会话 2 获得锁定 , 事情就会继续进行 。但是,由于元数据锁定系统的优先级性质,会话 3 具有锁定,会话 2 仍然等待 。
如果另一个写入会话进入并启动新事务并获取针对父表的写锁定,则即使会话 3 完成 , ALTER 仍将被阻止 。
只要我保持一个对父表打开元数据锁定的活动事务 , 子表上的 ALTER 将永远不会完成 。更糟糕的是,由于子表上的写锁定成功(但是完整语句正在等待获取父读锁定),所以针对子表的所有传入读取请求都将被阻止!
另外,请考虑一下您通常如何对无法完成的语句进行故障排除 。您查看已经打开较长时间的事务(在进程列表和 InnoDB 状态中) 。但由于阻塞线程现在比 ALTER 线程更年轻,因此您将看到的最旧的事务/线程是 ALTER。
这正是这种情况下发生的情况 。在准备发布时,我们的客户端正在运行 ALTER 语句并结合负载测试(一种非常好的做法?。┮匀繁K忱⒉?。问题是负载测试保持对父表打开一个活动的写事务 。这并不是说它只是一直在写,而是有多个线程 , 一个总是活跃的 。这阻止了 ALTER 完成并阻止对相对静态的子表的随后的读请求 。
幸运的是,这个问题有一个解决方案(除了从设计模式中驱逐外键) 。变量 max_write_lock_count[2] 可用于允许在写入锁定之后在读取锁定之前授予读取锁定连续写锁 。默认情况下,此变量设置为 18446744073709551615,如果你对该表发出 10,000 次写入/秒,那么你的读将被锁定 5800 万年……
我想修改mysql的等待超时时间怎么改my.cnf默认都是没有的,但其实你装的时候会在/usr/share/mysql 这个路径下有类似的 , 根据你数据库大小不同的推荐配置,有my-small.cnf,my-large.cnf等等,如果需要配置文件,选择一个拷到/etc下,重命名为my.cnf即可 , 默认超时时间等都在这里进行配置,这样启动会就会是你设置的默认值了
如果你在命令行里改 , 只会修改当前会话,退出重进或者重启mysql之后就会变回默认值
如何优化这个sql , 是在mysql中执行,比较慢,每次项目加载时都要等待一分多钟左右数据才出来,求教?。。?/h2>select m.*,a.agent_name from pos_merchant m
inner join agent_info a
on m.agent_no=a.agent_no
where m.merchant_no not IN(SELECT i.merchant_no from trans_info i where i.agent_no=a.agent_no)
ORDER BY m.id DESC
尽量不要用not in,改成not exists
C#连接mysql数据库,怎么设置超时时间MySQL查询超时的设置方法
为了优化OceanBase的query timeout设置方式,特调研MySQL关于timeout的处理,记录如下 。
[plain]
mysql show variables like '%time%';
---------------------------- -------------------
| Variable_name| Value|
---------------------------- -------------------
| connect_timeout| 10|
| datetime_format| %Y-%m-%d %H:%i:%s |
| delayed_insert_timeout| 300|
| flush_time| 1800|
| innodb_lock_wait_timeout| 50|
| innodb_old_blocks_time| 0|
| innodb_rollback_on_timeout | OFF|
| interactive_timeout| 28800|
| lc_time_names| en_US|
| lock_wait_timeout| 31536000|
| long_query_time| 10.000000|
| net_read_timeout| 30|
| net_write_timeout| 60|
| slave_net_timeout| 3600|
| slow_launch_time| 2|
| system_time_zone||
| time_format| %H:%i:%s|
| time_zone| SYSTEM|
| timed_mutexes| OFF|
| timestamp| 1366027807|
| wait_timeout| 28800|
---------------------------- -------------------
21 rows in set, 1 warning (0.00 sec)
重点解释其中几个参数:
connect_timeout:
The number of seconds that the mysqld server waits for a connect packet before respondingwith Bad handshake. The default value is 10 seconds as of MySQL 5.1.23 and 5 seconds before that.Increasing the connect_timeout value might help if clients frequently encounter errors of the form Lost connection to MySQL server at ‘XXX’, system error: errno.
解释:在获取链接时,等待握手的超时时间 , 只在登录时有效,登录成功这个参数就不管事了 。主要是为了防止网络不佳时应用重连导致连接数涨太快,一般默认即可 。
interactive_timeout:
The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect(). See alsowait_timeout.
解释:一个持续SLEEP状态的线程多久被关闭 。线程每次被使用都会被唤醒为acrivity状态,执行完Query后成为interactive状态,重新开始计时 。wait_timeout不同在于只作用于TCP/IP和Socket链接的线程,意义是一样的 。
MySQL可以配置连接的超时时间,这个时间如果做得太长 , 甚至到了10min,那么很可能发生这种情况,3000个链接都被占满而且sleep在哪,新链接进不来,导致无法正常服务 。因此这个配置尽量配置一个符合逻辑的值,60s或者120s等等 。
说人话:
命令行下面敲一个命令后,直至下一个命令到来之前的时间间隔为interactive_time , 如果这个时间间隔超过了interactive_timeout,则连接会被自动断开 , 下一个命令失败 。不过一般的mysql客户端都有自动重连机制,下一个命令会在重连后执行 。
[sql]
mysql set interactive_timeout = 1;
Query OK, 0 rows affected (0.00 sec)
mysql show session variables like '%timeout%';
---------------------------- ----------
| Variable_name| Value|
---------------------------- ----------
| connect_timeout| 10|
| interactive_timeout| 1|
| wait_timeout| 28800|
---------------------------- ----------
10 rows in set (0.00 sec)
=====
[sql]
mysql set wait_timeout = 1;
Query OK, 0 rows affected (0.00 sec)
【去泡杯茶,等会儿】
mysql show session variables like '%timeout%';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:7
Current database: *** NONE ***
---------------------------- ----------
| Variable_name| Value|
---------------------------- ----------
| connect_timeout| 10|
| interactive_timeout| 28800|
| wait_timeout| 28800|
---------------------------- ----------
10 rows in set (0.01 sec)
wait_timeout:
The number of seconds the server waits for activity on a noninteractive connection (连接上没有活动命令,可能是客户端喝咖啡去了 。)before closing it. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory.
On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client
这里顺带解释一下什么是non-interactive connection
Non-Interactive Commands
Just do a quick look up on a table without logging into the client, running the query then logging back out again.
You can instead just type one line using the ' -e ' flag.
[sql]
c:\mysql\bin\mysql -u admin -p myDatabase -e 'SELECT * FROM employee'
net_read_timeout / net_write_timeout
The number of seconds to wait for more data from a connection before aborting the read. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory. When the server is reading from the client, net_read_timeout is the timeout value controlling when to abort. When the server is writing to the client, net_write_timeout is the timeout value controlling when to abort. See also slave_net_timeout.
On Linux, the NO_ALARM build flag affects timeout behavior as indicated in the description of the net_retry_count system variable.
解释:这个参数只对TCP/IP链接有效,分别是数据库等待接收客户端发送网络包和发送网络包给客户端的超时时间,这是在Activity状态下的线程才有效的参数
JDBC setQueryTimeout函数:
为了避免查询出现死循环,或时间过长等现象 , 而导致线程阻塞,在获得Statement的实例后,stmt.setQueryTimeout(10); 避免因为查询导致程序出现线程阻塞 。
但昨天发现程序出现了,“ORA-01013: 用户请求取消当前的操作”的异常 。手工执行出错SQL语句发现,这个语句耗时20多秒 。因为setQueryTimeout(10),所以还没有执行完查询语句就抛出异常了 。使用setQueryTimeout(10)时一定要把时间设置的长一些,如60秒以上 。只要不导致线程长期阻塞,就可以 。太短了容易抛出,“ORA-01013: 用户请求取消当前的操作”的异常
JDBC实现setQueryTimeout的原理:
[java]
class IfxCancelQueryImpl extends TimerTask
implements IfmxCancelQuery
{
IfxStatement stmt;
Timer t = null;
public void startCancel(IfxStatement paramIfxStatement, int paramInt)
throws Exception
{
this.stmt = paramIfxStatement;
this.t = new Timer(true);
this.t.schedule(this, paramInt * 1000);
}
public void run()
{
try
{
this.stmt.cancel();
this.t.cancel();
}
catch (SQLException localSQLException)
{
this.t.cancel();
throw new Error(localSQLException.getErrorCode()":"localSQLException.getMessage());
}
}
}
jdbc 连接Mysql Communications link failure due to underlying exception: 非常纳闷,急求高手解决办法从题主给你内容来看 你获取连接应该就失败了
那么建议题主,做以下排查
1 通过 软件或者可视化界面 能否正常登陆你的数据库
如果能正确登陆至少说明 数据库层面没有问题
2加载驱动 和 获取连接 能否能到正确的连接
如果能获取到 连接 并且打印出 对象号 说明能正确获取连接
如果这两部都没有问题 那么才要继续查询
另外 你不贴代码 直接发报错信息 还只发了一部分 我们很难回答啊
【mysql等待时间怎么调 mysql查看正在执行的sql语句】mysql等待时间怎么调的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于mysql查看正在执行的sql语句、mysql等待时间怎么调的信息别忘了在本站进行查找喔 。
推荐阅读
- 两台路由器怎么不可以连接,两台路由器怎么不可以连接网络
- vb连接oracle9i数据库,vb 连接数据库
- sqlserversku错误,sqlserver926错误
- 辽宁如何做好线上推广销售,如何进行线上推广销售
- linux命令中文意思 linux命令含义
- flutter路由动画结束回调,flutter pageview动画
- 妆造拍摄是什么,造型妆容
- 英特尔10代怎么搭配显卡,英特尔十代的配置
- i方s音频java代码 java音乐播放器源码