MySQL 事务回滚不起作用


今天在写程序的时候发现一个奇怪的问题:
明明设置了事物非自动提交,但是当
回滚后,更新操作还是被执行了,并且不报任何错误.


下面是代码,代码是没有问题的:
[java] view plain copy
  1. import java.sql.Connection;  
  2. import java.sql.DriverManager;  
  3. import java.sql.PreparedStatement;  
  4. import java.sql.Statement;  
  5.   
  6.   
  7. public class MAIN {  
  8. public static void main(String[] args) throws Exception {  
  9.     save();  
  10. }  
  11. public static void save() throws Exception{  
  12.     Class.forName("com.mysql.jdbc.Driver");  
  13.     Connection conn = DriverManager  
  14.             .getConnection(  
  15.                     "jdbc:mysql://localhost:3306/javadb",  
  16.                     "root","1234");  
  17.   conn.setAutoCommit(false);  
  18.   System.out.println(conn.getAutoCommit()+"conn.getAutoCommit");  
  19.   PreparedStatement stmt = conn.prepareStatement("insert into t_stock (stockNo,qty) values ('001037',10)");  
  20.   try{  
  21.       stmt.executeUpdate();  
  22.       throw new RuntimeException();  
  23.   }catch(RuntimeException e){  
  24.       conn.rollback();  
  25.       e.printStackTrace();  
  26.       System.out.println("huigun...");  
  27.   }finally{  
  28.       if (stmt != null){  
  29.       stmt.close();  
  30.       }  
  31.       if (conn != null){  
  32.        conn.close();  
  33.       }  
  34.   }  
  35. }  
  36. }  


-----------------------------------------
首先分析代码:代码中sql语句执行以后,并没有commit操作
而是出了异常,进入了回滚,但是回滚没有成功,
说明肯定是设置conn.setAutoCommit(false);这句话
没有成功,也就是没有起作用,然后就考虑到
数据库是不是没有设置非自动提交,然后去看了看:
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.04 sec)
可以看到数据库设置的是自动提交:
然后尝试把他设置成非自动提交:
mysql> set autocommit = 0;
这里设置成:
值0和OFF都是一样的,当然,1也就表示ON
----------------------------
但是当,关闭当前mysql窗口,又打开另一个窗口的时候
发现
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.04 sec)


事物自动提交依然是开启的,也就是咱们的设置没有起作用,
仅仅是在当前窗口起了作用对吧.


所以就考虑,是不是数据库不支持事物
-------------------------
然后查到下面资料:
MySQL默认的存储引擎是MyISAM
可以通过:
show engines;
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+------------------------------------------------- --------------+--------------+------+------------+
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MyISAM             | DEFAULT | MyISAM storage engine                                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| InnoDB             | YES     | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
+--------------------+---------+------------------------------------------------
而MyISAM存储引擎不支持事务处理,
所以改变autocommit没有什么作用。
但不会报错.所以一旦发生了这样的问题,很难排错.


接下来,咱们要做的就很明确了:
ALTER TABLE tb_chengji ENGINE = InnoDB;
修改表的存储引擎的类型,InnoDB是支持的,咱们可以看看;
这样再测试就好了
---------------------------------------
下面是找了,所有存储引擎类型的解释:
MySQL 数据表主要支持六种类型 ,分别是:BDB、HEAP、ISAM、MERGE、MYISAM、InnoBDB。
这六种又分为两类,一类是”事务安全型”(transaction-safe),包括BDB和InnoDB;其余都属于第二类,称为”非事务安全型”(non-transaction-safe)。
BDB 全称是”Brekeley DB”,它是Mysql最早的具有事务能力的表的类型,由Sleepycat Software 
(http://www.sleepycat.com)开发。它提供了事务控制能力功能,它确保一组命令全部执行成功,
或者当任何一个命令出现错误时所有命令的结果都被回退,可以想像在电子银行中事务控制能力是非常重要的。
支持COMMIT、ROLLBACK和其他事务特性。最新版本的Mysql已经计划移除对BDB的支持,转而全力发展InnoDB。
InnoDB 是较新的事务安全型存储引擎,用于事务处理应用程序,支持BDB的几乎所有特性,并具有众多新特性,包括ACID事务支持。
特性:
事务处理机制
支持外链
崩溃后能立即恢复
支持外键功能,级联删除
支持并发能力
在硬盘上的存储方式:InnoBDB frm
最新版本的Mysql已经计划移除对BDB的支持,转而全力发展InnoDB。InnoDB对Mysql有更好的特性支持,而且开发社区活跃。
MyISAM 默认的MySQL插件式存储引擎,它是基于ISAM类型,但它增加了许多有用的扩展,它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。注意,通过更改STORAGE_ENGINE配置变量,能够方便地更改MySQL服务器的默认存储引擎。
优点:
1.比ISAM表更小,所占资源更少
2.可以在不同平台间二进制移植表的类型在创建表时指定。
ISAM 是MyISAM类型出现之前MySQL表使用的默认类型,现在已经被MyISAM代替。
Memory (HEAP) 是MySQL表中访问最快的表,将所有数据保存在RAM中,在需要快速查找引用和其他类似数据的环境下,可提供极快的访问。注意,这种类型下数据是非持久化设计的,它一般适应于临时表,如果MySQL或者服务器崩溃,表中数据全部丢失。
Merge 是一种值得关注的新式表,它是由一组MyISAM表组成,之所合并主要出于性能上考虑,因为它能够提高搜索速度,提高修复效率,节省磁盘空 间。允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。有时它以 MRG_MYISAM 名称出现。
Archive 为大量很少引用的历史、归档、或安全审计信息的存储和检索提供了完美的解决方案。
Federated 能够将多个分离的MySQL服务器链接起来,从多个物理服务器创建一个逻辑数据库。十分适合于分布式环境或数据集市环境。
NDBCluster/Cluster/NDB MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有最高的正常工作时间和可用性。
CSV 使用标准的CSV格式,由逗号隔开的文本文件,适应于外部数据交换
Blackhole 它会接受数据但不保存,而且对任何检索请求返回一个空集。它一般适应于数据会被自动复制并不进行本地保存的分布式数据库设计。(不确定的)似乎也可以用于临时禁止/忽略对数据库的应用程序输入。
Example 这是一个测试引擎,你可以创建一个这样的表,但既不能写入数据,也不能检索数据。它似乎是一个针对MySql开发者提供的示例引擎。
有关操作和查看表类型的命令语法如下
--------------------------------------
-- 创建表时指定表类型的方法
CREATE TABLE `message` (
`id` int(11) NOT NULL auto_increment,
`sender` varchar(255) default NULL,
`receiver` varchar(255) default NULL,
`content` text,
`is_read` char(1) default 'N',
`send_time` datetime default NULL,
`del_flag` tinyint(4) default '0',
PRIMARY KEY (`id`)
) ENGINE=MYISAM;
-- 也可以创建后更改:
ALTER TABLE `message` ENGINE = INNODB;
-- 查看表类型(存储引擎)
SHOW TABLE STATUS FROM `test`;
-- -- 结果为数据库test中所有表的信息,其中第二项type即是表的类型。
-- 查看表类型(存储引擎)2
SHOW CREATE TABLE `message`;
-- -- 结果为表message创建时的信息,其中有TYPE或ENGINE一项,指定了表的类型(存储引擎)。
-- show tables不能得到表类型的信息。
-------------------------------------
注意:老版本的MySQL使用 TYPE而不是ENGINE(例如,TYPE = MYISAM)。MySQL 5.1为向下兼容而支持这个语法,但TYPE现在被轻视,而ENGINE 是首先的用法。 一般地,ENGINE选项是不必要的;除非默认已经被改变了,MyISAM是默认存储引擎。
数据表的可移植性
常用的数据移植方法:把数据表的内容导出到一个文本文件中,然后拷贝到硬盘上,然后导入目标数据库里面。
就文件层次的操作来说,某些数据表是可以直接单独拷贝表文件来移动的
SAM No
MyIASM Yes
BDB No
InnoBDB Yes
以上参考自:https://blog.csdn.net/lidew521/article/details/53192774
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页