当前位置:   article > 正文

mysql url batch_mysql几个参数(编码,预编译,批处理)

cacheprepstmts=yes

背景

这两天在做数据同步项目的联调,测试过程中发现针对mysql的一些使用上存在一些问题,比如batch不起效果,编码问题,预编译失效等等。 这里总结一下,做一下记录,希望对遇到类似问题的有所帮助

内容

编码问题

网上针对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\_%';

结果:

925789ab5e68cd2b86dc89a6e944c2e2.png

character_set_server编码为latin1 , 而我数据表的编码为utf-8,这也就难怪出现乱码了,最后设置下根据不同的数据表设置characterEncoding即可。

预编译问题

具体的参数设置,这里面已经写的比较详细了,我就简单的从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);

38ac104d853af699aa3f4d3bb8a03e73.png

大小: 27.5 KB

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2011-11-22 16:08

浏览 11947

评论

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/程序质量控制师/article/detail/61853
推荐阅读
相关标签
  

闽ICP备14008679号