背景
这两天在做数据同步项目的联调,测试过程中发现针对mysql的一些使用上存在一些问题,比如batch不起效果,编码问题,预编译失效等等。 这里总结一下,做一下记录,希望对遇到类似问题的有所帮助
内容
编码问题
官方文档: http://dev.mysql.com/doc/refman/4.1/en/connector-j-reference-charsets.html
网上针对mysql的中文编码问题,已经有不少文章进行介绍,大概步骤如下:
1. 设置my.cnf中, 设置default-character-set=utf8
2. 创建表时指定编码,create table {...} ENGINE = InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ;
3. 客户端链接url上,指定编码参数: useUnicode=true&characterEncoding=UTF-8
因为项目是做一个数据同步项目,所以需要处理的是客户端的编码问题(server端的编码会由DBA搞定),刚开始时没设置客户端链接参数,在程序中手工的将源库(GBK),转成了目标库(UTF-8)的编码,构造了特定编码的SQL。
但是用构造出来的UTF-8编码的string流,通过jdbcTemplate执行的时候,目标库中针对中文字符出现了乱码。
大致猜测应该是在driver层面没有正确的送出数据流到目标数据库上,具体编码处理代码如下:
类:com.mysql.jdbc.ConnectionImpl
方法: checkServerEncoding()
private void checkServerEncoding() throws SQLException {
if (getUseUnicode() && (getEncoding() != null)) { //位置1
// spec'd by client, don't map
return;
}
String serverEncoding = (String) this.serverVariables.get("character_set");
if (serverEncoding == null) {
// must be 4.1.1 or newer?
serverEncoding = (String) this.serverVariables.get("character_set_server");
}
String mappedServerEncoding = null;
if (serverEncoding != null) {
mappedServerEncoding = CharsetMapping
.getJavaEncodingForMysqlEncoding(serverEncoding.toUpperCase(Locale.ENGLISH), this);
}
//
// First check if we can do the encoding ourselves
//
if (!getUseUnicode() && (mappedServerEncoding != null)) {
SingleByteCharsetConverter converter = getCharsetConverter(mappedServerEncoding);
if (converter != null) { // we know how to convert this ourselves
setUseUnicode(true); // force the issue
setEncoding(mappedServerEncoding);
return;
}
}
}
说明:
1. 首先会校验useUnicode和characterEncoding参数的设置(即为url中的参数设置),如果有则直接返回,不去自动猜测db server的编码
2. 读取mysql variables数据,提取character_set和character_set_server的编码做为characterEncoding编码
3. 基于characterEncoding构造了SingleByteCharsetConverter进行编码转化,最终录入到目标库
原理搞清楚了,基本这编码问题也就很容易解决了。
1. check下mysql variables变量:
命令: show variables like 'character\_set\_%';
结果:
character_set_server编码为latin1 , 而我数据表的编码为utf-8,这也就难怪出现乱码了,最后设置下根据不同的数据表设置characterEncoding即可。
预编译问题
相关文章: http://blog.csdn.net/axman/article/details/6913527
具体的参数设置,这里面已经写的比较详细了,我就简单的从driver层面来给大家介绍下。
类:com.mysql.jdbc.ConnectionImpl
方法: initializePropsFromServer()
//
// Users can turn off detection of server-side prepared statements
//
if (getUseServerPreparedStmts() && versionMeetsMinimum(4, 1, 0)) {
this.useServerPreparedStmts = true;
if (versionMeetsMinimum(5, 0, 0) && !versionMeetsMinimum(5, 0, 3)) {
this.useServerPreparedStmts = false; // 4.1.2+ style prepared
// statements
// don't work on these versions
}
}
说明:
1. getUseServerPreparedStmts()主要是从connection properties中提取useServerPrepStmts变量的设置(useServerPrepStmts=true/false)
2. prepareStatement使用代码,也是在ConnectionImpl.prepareStatement方法中
- 针对特定的sql,CREATE TABLE/SET操作,不使用预编译
- prepStmtCacheSqlLimit长度限制,默认256。超过该长度后,不使用预编译
- cachePrepStmts设置是否对预编译使用local cache
- prepStmtCacheSize指定了local cache的大小,使用了LRU进行逐出
- 最后使用com.mysql.jdbc.ServerPreparedStatement和db server的建立映射
3. 如果不开启(useServerPrepStmts=false),使用com.mysql.jdbc.PreparedStatement进行本地SQL拼装,最后送到db上就是已经替换了?后的最终SQL
总结一下,注意几个参数即可:
- useServerPrepStmts=true/false
- prepStmtCacheSqlLimit=256
- cachePrepStmts=true/false
- prepStmtCacheSize=256
预编译cache在链接池层面都已经有类似的实现,可以不开启driver的cache参数。
可以通过命令: show global status like '%prepare%' , 查看db server端预编译的使用情况
批处理问题
mysql默认关闭了batch处理,需要设置rewriteBatchedStatements=true参数进行打开。
使用代码:com.mysql.jdbc.StatementImpl,com.mysql.jdbc.PreparedStatement的executeBatch()方法
最后
总结一下,主要是几个参数的使用:
BasicDataSource dbcpDs = new BasicDataSource();
dbcpDs.addConnectionProperty("useServerPrepStmts", "true");
dbcpDs.addConnectionProperty("rewriteBatchedStatements", "true");
dbcpDs.addConnectionProperty("characterEncoding", encoding);
- 大小: 27.5 KB
分享到:
相关推荐
Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql编译安装Mysql...
MySQL预编译功能
该批处理文件可以在您忘记密码的时候,一键重新设置为新的密码
Tomcat和mysql的启动、关闭、重启批处理脚本命令,支持windows和linux下的使用,其中tomcat可以参考我的博客 https://blog.csdn.net/qq_36379495/article/details/80604345
Mysql数据库备份批处理Mysql数据库备份批处理Mysql数据库备份批处理Mysql数据库备份批处理
MySQL5.6实战部署,编译安装MySQL5.6.22,编译参数详解
mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql启动命令mysql...
解压文件后 直接运用bat批处理 直接安装mysql服务 环境变量等 ,秒安装。 安装完成后,以后开机会自启动mysql服务!里面有服务的启动关闭和卸载的文档教程!
mysql 服务启动与关闭脚本,Windows 批处理,双击启动或者关闭
这个mysql数据库备份批处理,其中把数据库的用户名换成你自己的用户名,数据库的密码换成自己的密码,数据库名换成要备份的数据库名,然后保存即可
本文为大家分享了MySQL预编译功能,供大家参考,具体内容如下 1、预编译的好处 大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能。什么是预编译功能呢?它有什么好处呢? 当客户发送一条SQL语句...
用一个批处理文件连接mysql,其中用如何连接和如何备份一mysql数据库
批处理程序:判断mysql服务是否开启,未开启则打开,根据文本文件的编号给备份sql文件命名并保存在指定目录下,启动delphi程序,将文本文件的内容编号加1,根据配置文件保留备份文件数目将N天前的备份文件删除,...
NULL 博文链接:https://yuexiaowen.iteye.com/blog/1322330
Java之JDBC连接数据库实现增删改查(2018 使用Dao层实现 完美封装解决硬编码问题 使用预编译对象PreparedStatement) 配置文件 db.properties(保存数据库账号和密码等) 工具类 JDBCUtil.java(抽取公共部分,解决硬...
我自己写的mysql免安装的批处理文件,谢谢
全国省市区编码mysql全国省市区编码mysql全国省市区编码mysql全国省市区编码mysql
mysql 批量执行 sql文件 批处理,参数和执行方法见附件txt文档
mysql绿色安装 1.使用批处理生成mysql的运行配置文件my.ini 2.加入windows的后台服务 3.修改权限,使远程机器能访问此服务