服务器断网事务未提交导致MYSQL锁表问题(ADSL拨号上网)

环境描述:

由于特殊原因服务器的网络是电信ADSL拨号上网的,用"自动切换IP精灵"进行自动断网重连,每次重新连上网络需要2s时间,设置2小时切换一次网络。

        MYSQL数据库在远程一台服务器上,另有一台测试数据库(MYSQL,也是ADSL拨号)。

发现程序部署上去后,总会莫名的锁表,而连接测试数据库则没有问题。加入详细日志后发现是因为开启事务后,在程序更新多张表期间,“自动切换IP精灵”切换网络导致网络中断,事务未提交导致锁表! 那为什么测试数据库没有问题?

        后来发现线上MYSQL版本是5.7.14,测试数据库版本是5.0.27,查找数据库版本更新资料发现:自5.5以后,其中有一条新增功能是 

改善事务处理中的元数据锁定。例如,事物中一个语句需要锁一个表,会在事物结束时释放这个表,而不是像以前在语句结束时释放表(参考文章http://blog.csdn.net/chajinglong/article/details/52939350)。 
,也就是说 自5.5版本之后information_schema库增加了INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS等几张与事务相关的表,事务的元数据锁定将更好的由事务表控制。这也是为什么测试数据库没有锁表的原因。  

我原来的理解是断网后数据库会自动释放锁定的表,哪怕事务没有提交,因为连接中断数据库也会释放。

其实不是,为此专门做个测试:

        cmd开启两个数据库的连接:

               连接一:

mysql>set autocommit = 0;

mysql>begin;

mysql>update user set name='aa' where id = 1;

不提交事务,再打开 另一个窗口

连接二:

mysql>set autocommit = 0;

mysql>begin;

mysql>update user set name='aa' where id = 1;

则连接二处于挂起状态


如果此时关闭连接一窗口,则连接二会立刻返回执行结果!也就是关闭窗口,连接中断 数据库会自动释放事务 立刻回滚。

但是当我用连接池连接数据库并模拟 断网的情况时,通过SELECT * FROM information_schema.INNODB_TRX;会看到有事务未提交,并且没有因为断网数据库自动回滚(一时想不明白为何会如此)。

解决未提交事务方法是:

开启事务后,先执行一次select 查询,然后执行SELECT TRX_MYSQL_THREAD_ID FROM INFORMATION_SCHEMA.INNODB_TRX  WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID(); 获得当前connection连接的trx_mysql_thread_id,最后 kill trx_mysql_thread_id的值,即可删除未提交事务。

        各位如果有更好的解决方法,可告知下。

你可能感兴趣的:(服务器断网事务未提交导致MYSQL锁表问题(ADSL拨号上网))