为了减少数据库连接的次数,以及加快数据更新的时间,我们习惯采用批处理的方式来向数据库插入数据。当然这没有错,但是如果在写代码的时候你没有注意或者不了解其中的一些原理或者细节,那么可能就无法得到你想要的结果,甚至适得其反。
下面说下使用Java向MySQL数据库执行【批处理更新】时可能会存在的一个风险,其他编程语言也可能存在这种风险。
先看如下Java代码:
classes表定义:
CREATE TABLE `classes` ( `sid` int(11) NOT NULL AUTO_INCREMENT, `class_name` varchar(20) NOT NULL, `class_num` varchar(10) NOT NULL, PRIMARY KEY (`class_num`), KEY `sid` (`sid`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1
这段代码很简单,就是向表classes插入两条数据,采用批处理的方式。从表面上看这段代码并没有什么问题,而且就算执行后你也看不出什么,因为数据成功插入到了表classes中,没有出现任何错误。
那么上面代码究竟有什么问题呢?我们执行上面的代码,然后在MySQL端查看:
从图中可以看到数据已被成功插入表中。这时候我们再查看后台的MySQL二进制日志文件(需要提前开启,关于如何开启可参考我之前写的文章《MySQL的日志文件》):
从info列可以看出,后台在处理这个批处理时,开启了两个事务(每个BEGIN和COMMIT构成一个事务),每个事务只执行一条插入:后台压根就没有执行批处理操作!!!为什么会这样?我们客户端代码不是执行了stmt.addBatch(sql)和stmt.executeBatch()命令吗?
这时候打开通用日志,就可以发现原因:
原来客户端连接上MySQL服务后,MySQL后台默认执行了一些命令,这些命令中包括了SET autocommit=1,这个命令告知MySQL开启事务自动提交,即是把每条命令(增删改查)当做一个事务处理,并且执行后立即提交,这是MySQL的默认处理方式。
所以就出现了上面二进制日志记录所描述的情况:每个Insert操作都被单独作为一个事务执行。
那这样有什么坏处呢?首先每个语句都启动一个事务来处理,会给服务器增加额外的开销,数据量大时响应可能会变得很慢;再一个是在执行的过程中,如果出错,那么前面的插入将无法回滚。
比如我们将代码改改,如:
由代码可见,第2条语句由于在后面加入了“error“,可以知道它会执行错误,这时候我们当然希望它会全部回滚,回到之前的状态(不要插入任何数据),因为我们调用了批处理,要么全部成功,要么全部失败。
但我们执行后却是:
后台二进制日志:
由图可见,虽然存在错误,但还是成功插入了第一条数据,这是我们不愿看到的,我们希望退回到未执行该操作时的状态。导致出现这种情况的原因,如前所述,是因为客户端连接上MySQL服务后,MySQL服务默认执行了SET autocommit=1这个命令。
那我们如何避免这种情况呢?很简单,既然是由于SET autocommit=1导致的,那么我们就让SET autocommit=0。代码如下:
在后台先把5这条数据删掉:
然后执行上面的Java代码,这时候查看后台通用日志:
可见连接成功后后台已将autocomit设置为0。
此时再查看classes表:
并未插入任何数据。
再查看二进制日志:
里面只有删除操作,并未执行任何插入操作。
我们将代码再改为:
执行该代码,然后查看表classes:
数据已被成功插入。此时再查看二进制日志:
可以看到只有一个BEGIN … COMMIT,两个插入语句都被包含在里面了,说明MySQL服务器将其作为同一个事务来处理,所以就很好解释上面二进制日志未记录任何插入操作的原因,因为只有一个事务,所以当其中有一条语句出错时,事务会全部回滚(这是事务的原子性隔离级别决定的,关于事务的隔离级别,可参考我之前写的文章《MySQL的事务隔离级别》)。
这就是使用Java做批处理时可能存在的一个风险,而且当你处理的是涉及具体金额的数据的时候尤为重要。我以前也这样写代码,或者经常在网上看到conn.setAutoCommit(false)这样的建议,但那时候并未知晓其中的道理,然后最近也是由于一个很偶然的机会才从MySQL的日志文件中发现了具体的原因,所以整理出来与大家分享。
相关推荐
BAT批处理脚本是Windows操作系统中的一个...在实际使用时,需要注意安全问题,避免在不理解脚本内容的情况下直接运行,防止潜在的风险。同时,学习和理解批处理脚本的编写也能提升用户在日常工作中对系统管理的技能。
批处理文件允许用户将多条命令写入一个单一的文件中,当运行这个文件时,系统会依次执行这些命令,就像你在命令提示符窗口中逐行输入一样。这对于执行重复性的系统管理任务,如安装软件、配置环境变量、备份数据等,...
首先,Java提供了一个内置的`java.lang.Runtime`类,它可以让我们与运行Java虚拟机的同一操作系统进行交互,包括执行系统命令。我们可以使用`Runtime.getRuntime().exec()`方法来执行外部命令或脚本。例如,如果你有...
此外,为了安全起见,从不可信源获取的批处理脚本应当谨慎运行,以免引入潜在的安全风险。 总的来说,"windows java环境一键配置.zip" 提供了一种方便快捷的方式来配置Windows上的Java开发环境,减少了手动设置环境...
- 安全性:捆绑JRE可能会增加安全风险,因为JRE更新可能会被绕过,从而导致潜在的漏洞。 6. **其他打包选项**: - 容器化:使用Docker等容器技术,将Java应用打包为轻量级运行环境,提供一种跨平台的解决方案。 ...
批处理文件v0.1可能是该工具的一个版本,它可能是用Windows批处理语言编写,能够自动检测Java安装位置,并将必要的路径添加到系统环境变量中。 使用这样的工具,开发者不再需要担心因环境变量配置错误导致的各类...
Java环境变量一键配置脚本是Java开发中必不可少的工具,它极大地简化了Java开发者在不同操作系统上设置环境变量的...然而,为了确保安全,使用脚本时应确保来源可靠,并且理解脚本执行的每一步,避免潜在的安全风险。
在这个特定的工具中,批处理脚本可能包含了设置以上三个关键环境变量的指令,并可能包含了一些逻辑判断,比如检查Java是否已经安装,或者自动检测Java的安装位置。 然而,"浮夸供 JAVA环境变量(本工具会报毒,信就...
- 在执行任何脚本之前,务必了解其内容,防止潜在的安全风险。 - 使用`chmod`命令更改脚本的权限,赋予执行权限(如`chmod +x javaPathShell.sh`)。 - 避免在脚本中硬编码敏感信息,例如路径,因为这可能导致...
Yasca是一款开源的安全扫描器,它旨在帮助用户识别和修复潜在的代码漏洞和安全风险,特别是针对Java应用程序。 【描述】"基于Java的漏洞检测程序Yasca.zip"描述了这个压缩包的核心内容,即一个运行在Java环境下的...
在Java编程中,有时我们需要对数据库查询结果进行分页显示,传统的MySQL数据库中,我们通常会使用`LIMIT`和`OFFSET`子句来实现这一功能。...在开发过程中,务必注意数据安全,避免SQL注入等潜在风险。
Yasca通过扫描目标系统或应用,识别潜在的安全风险,帮助管理员及时发现并修复问题,提升系统的安全性。 【描述】Yasca是一款功能强大的开源漏洞扫描器,它能够在多种操作系统环境下运行,包括Windows、Linux和...
【标题】:“性能规模风险初评hibernate共4页.pdf.zip”这个文件名暗示了文档内容可能涉及对使用Hibernate框架进行系统开发时,关于性能、规模和潜在风险的初步评估。Hibernate是一个流行的Java持久层框架,用于简化...
Java反编译是将已编译的字节码(.class文件)转换回源代码(.java文件)的过程,这在软件开发、逆向工程、调试和教学等场景中非常...同时,注意安全风险,不要随意运行未知来源的exe文件,以防病毒或恶意软件的感染。
- **安全性考虑**:将JRE与应用程序一起打包可能会带来安全风险,尤其是当用户不信任应用程序来源时。 - **性能影响**:包含完整JRE的可执行文件体积会相对较大,可能会影响分发和下载体验。 - **维护成本**:每次...
- **权限控制**:确保执行脚本的账户具有足够的权限,同时也要注意不要给予过高的权限,防止潜在的安全风险。 - **性能优化**:避免在脚本中执行不必要的全表扫描或长时间运行的查询,确保批量执行的效率。 综上所...
在运行JAVE之前,你可能还需要配置环境变量,确保系统能够找到Java执行环境。 转码过程中,JAVE会考虑音频的编码参数,如采样率、位深度、声道数等,可以根据需要调整这些参数来优化音频质量。此外,JAVE还支持...
Jakarta Tomcat 5.0 是一个非常重要的Java Web应用服务器,它主要用于运行基于Java Servlet和JavaServer Pages (JSP...在使用过程中,务必注意环境变量的设置,确保与系统环境兼容,同时关注安全更新,以防潜在的风险。
这个服务允许用户检测网络上的开放端口,从而了解系统可能暴露的服务、识别潜在的安全风险或者进行常规的网络管理。 首先,我们要理解什么是Java。Java是一种广泛使用的面向对象的编程语言,具有跨平台的能力,这...
6. **运行批处理文件**:“设置IE.bat”可能是一个批处理文件,包含了自动执行上述步骤的命令。运行这个文件前,也需要了解其内容以确保安全。 7. **创建快捷方式**:“IE.lnk”是IE浏览器的快捷方式,可能已经预设...