- 浏览: 980070 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
JDBC驱动初始化-Mysql:http://donald-draper.iteye.com/blog/2342010
JDBC连接的获取:http://donald-draper.iteye.com/blog/2342011
Mysql负载均衡连接的获取:http://donald-draper.iteye.com/blog/2342089
Mysql主从复制读写分离连接的获取:http://donald-draper.iteye.com/blog/2342108
ConnectionImp创建MysqlIO :http://donald-draper.iteye.com/blog/2342959
Mysql预编译SQL:http://donald-draper.iteye.com/blog/2342960
MysqlSQL PreparedStatement的查询:http://donald-draper.iteye.com/blog/2343083
MySQL ServerPreparedStatement查询:http://donald-draper.iteye.com/blog/2343124
前几篇文章中,我们谈到连接的获取,mysqlIO的初始化,今天来看一下SQL的预编译,从下面这一句开始:
//ConnectionImpl
//获取sql的PreparedStatement
从上可以看出prepareStatement方法首先,检查连接是否关闭,关闭则直接返回;
根据server是否可以预编译sql和PreparedStatement是否为ServerPreparedStatement信息,
来确定返回的prepareStatement是ServerPreparedStatement还是com.mysql.jdbc.PreparedStatement,server可以预编译sql,且PreparedStatement为ServerPreparedStatement则返回的是ServerPreparedStatement,否则返回的是com.mysql.jdbc.PreparedStatement。
这里有两点要看,先看第一点ServerPreparedStatement,再看第二点clientPrepareStatement
1.
//如果缓存中不存在sql对应的ServerPreparedStatement,则创建
2.
//如果server不可以预编译sql,则创建sql对应的为clientPrepareStatement
//如果缓存中不存在sql对应的ServerPreparedStatement,则创建
//预编译sql
来看这一句:
//MysqlIO发送sql命令
//MysqlIO
从上面可以看出,ServerPreparedStatement实际上就是通过MysqlIO,将sql发送到Server端。
2.
//如果server不可以预编译sql,则创建sql对应的为clientPrepareStatement
总结:
prepareStatement方法首先,检查连接是否关闭,关闭则直接返回;
根据server是否可以预编译sql和PreparedStatement是否为ServerPreparedStatement信息,
来确定返回的prepareStatement是ServerPreparedStatement还是com.mysql.jdbc.PreparedStatement,server可以预编译sql,且PreparedStatement为ServerPreparedStatement则返回的是ServerPreparedStatement
否则返回的是com.mysql.jdbc.PreparedStatement。ServerPreparedStatement实际上就是通过MysqlIO,将sql发送到Server端。
//LRUCache,LRUCache实际上是一个Map
JDBC连接的获取:http://donald-draper.iteye.com/blog/2342011
Mysql负载均衡连接的获取:http://donald-draper.iteye.com/blog/2342089
Mysql主从复制读写分离连接的获取:http://donald-draper.iteye.com/blog/2342108
ConnectionImp创建MysqlIO :http://donald-draper.iteye.com/blog/2342959
Mysql预编译SQL:http://donald-draper.iteye.com/blog/2342960
MysqlSQL PreparedStatement的查询:http://donald-draper.iteye.com/blog/2343083
MySQL ServerPreparedStatement查询:http://donald-draper.iteye.com/blog/2343124
前几篇文章中,我们谈到连接的获取,mysqlIO的初始化,今天来看一下SQL的预编译,从下面这一句开始:
PreparedStatement ps = con.prepareStatement("select count(*) from ?");
//ConnectionImpl
//获取sql的PreparedStatement
public PreparedStatement prepareStatement(String sql) throws SQLException { //委托给prepareStatement(String sql, int resultSetType, int resultSetConcurrency) return prepareStatement(sql, 1003, 1007); } //预编译PreparedStatement public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { //检查连接是否关闭,关闭则返回 checkClosed(); com.mysql.jdbc.PreparedStatement pStmt = null; boolean canServerPrepare = true;//server是否可以预编译sql String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql) : sql; //判断server是否可以预编译sql if(useServerPreparedStmts && getEmulateUnsupportedPstmts()) canServerPrepare = canHandleAsServerPreparedStatement(nativeSql); //server可以预编译sql,且PreparedStatement为ServerPreparedStatement if(useServerPreparedStmts && canServerPrepare) { //如果Server需要缓存PreparedStatement if(getCachePreparedStatements()) //锁定server缓存, private LRUCache serverSideStatementCache; synchronized(serverSideStatementCache) { //从缓存中移除sql对应的ServerPreparedStatement pStmt = (ServerPreparedStatement)serverSideStatementCache.remove(sql); if(pStmt != null) { ((ServerPreparedStatement)pStmt).setClosed(false); pStmt.clearParameters(); } if(pStmt == null) try { //如果缓存中不存在sql对应的ServerPreparedStatement,则创建 pStmt = ServerPreparedStatement.getInstance(this, nativeSql, database, resultSetType, resultSetConcurrency); if(sql.length() < getPreparedStatementCacheSqlLimit()) ((ServerPreparedStatement)pStmt).isCached = true; //设置结果集类型 pStmt.setResultSetType(resultSetType); //设置结果集并发策略 pStmt.setResultSetConcurrency(resultSetConcurrency); } catch(SQLException sqlEx) { if(getEmulateUnsupportedPstmts()) { pStmt = (com.mysql.jdbc.PreparedStatement)clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); if(sql.length() < getPreparedStatementCacheSqlLimit()) serverSideStatementCheckCache.put(sql, Boolean.FALSE); } else { throw sqlEx; } } } else try { //如果Server不缓存PreparedStatement,则直接创建对应的ServerPreparedStatement pStmt = ServerPreparedStatement.getInstance(this, nativeSql, database, resultSetType, resultSetConcurrency); pStmt.setResultSetType(resultSetType); pStmt.setResultSetConcurrency(resultSetConcurrency); } catch(SQLException sqlEx) { if(getEmulateUnsupportedPstmts()) pStmt = (com.mysql.jdbc.PreparedStatement)clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); else throw sqlEx; } } else { //如果server不可以预编译sql,则创建sql对应的为clientPrepareStatement pStmt = (com.mysql.jdbc.PreparedStatement)clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); } return pStmt; }
从上可以看出prepareStatement方法首先,检查连接是否关闭,关闭则直接返回;
根据server是否可以预编译sql和PreparedStatement是否为ServerPreparedStatement信息,
来确定返回的prepareStatement是ServerPreparedStatement还是com.mysql.jdbc.PreparedStatement,server可以预编译sql,且PreparedStatement为ServerPreparedStatement则返回的是ServerPreparedStatement,否则返回的是com.mysql.jdbc.PreparedStatement。
这里有两点要看,先看第一点ServerPreparedStatement,再看第二点clientPrepareStatement
1.
//如果缓存中不存在sql对应的ServerPreparedStatement,则创建
pStmt = ServerPreparedStatement.getInstance(this, nativeSql, database, resultSetType, resultSetConcurrency);
2.
//如果server不可以预编译sql,则创建sql对应的为clientPrepareStatement
pStmt = (com.mysql.jdbc.PreparedStatement)clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
//如果缓存中不存在sql对应的ServerPreparedStatement,则创建
pStmt = ServerPreparedStatement.getInstance(this, nativeSql, database, resultSetType, resultSetConcurrency);
public class ServerPreparedStatement extends com.mysql.jdbc.PreparedStatement { //JDBC4ServerPreparedStatement构造函数 private static final Constructor JDBC_4_SPS_CTOR; protected static final int BLOB_STREAM_READ_BUF_SIZE = 8192; private static final byte MAX_DATE_REP_LENGTH = 5; private static final byte MAX_DATETIME_REP_LENGTH = 12; private static final byte MAX_TIME_REP_LENGTH = 13; private boolean hasOnDuplicateKeyUpdate; private boolean detectedLongParameterSwitch; private int fieldCount; private boolean invalid; private SQLException invalidationException; private boolean isSelectQuery;//是否是select查询 private Buffer outByteBuffer; private BindValue parameterBindings[]; private Field parameterFields[];//参数域 private Field resultFields[];//结果域 private boolean sendTypesToServer; private long serverStatementId; private int stringTypeCode; private boolean serverNeedsResetBeforeEachExecution; protected boolean isCached; private boolean useAutoSlowLog; private Calendar serverTzCalendar; private Calendar defaultTzCalendar; private boolean hasCheckedRewrite; private boolean canRewrite; private int locationOfOnDuplicateKeyUpdate; static { if(Util.isJdbc4()) try { JDBC_4_SPS_CTOR = Class.forName("com.mysql.jdbc.JDBC4ServerPreparedStatement").getConstructor(new Class[] { com.mysql.jdbc.ConnectionImpl.class, java.lang.String.class, java.lang.String.class, Integer.TYPE, Integer.TYPE }); } catch(SecurityException e) { throw new RuntimeException(e); } catch(NoSuchMethodException e) { throw new RuntimeException(e); } catch(ClassNotFoundException e) { throw new RuntimeException(e); } else JDBC_4_SPS_CTOR = null; } //获取ServerPreparedStatement实例 protected static ServerPreparedStatement getInstance(ConnectionImpl conn, String sql, String catalog, int resultSetType, int resultSetConcurrency) throws SQLException { if(!Util.isJdbc4()) return new ServerPreparedStatement(conn, sql, catalog, resultSetType, resultSetConcurrency); return (ServerPreparedStatement)JDBC_4_SPS_CTOR.newInstance(new Object[] { conn, sql, catalog, Constants.integerValueOf(resultSetType), Constants.integerValueOf(resultSetConcurrency) }); IllegalArgumentException e; e; throw new SQLException(e.toString(), "S1000"); e; throw new SQLException(e.toString(), "S1000"); e; throw new SQLException(e.toString(), "S1000"); e; Throwable target = e.getTargetException(); if(target instanceof SQLException) throw (SQLException)target; else throw new SQLException(target.toString(), "S1000"); } //ServerPreparedStatement构造函数 protected ServerPreparedStatement(ConnectionImpl conn, String sql, String catalog, int resultSetType, int resultSetConcurrency) throws SQLException { super(conn, catalog); hasOnDuplicateKeyUpdate = false; detectedLongParameterSwitch = false; invalid = false; sendTypesToServer = false; stringTypeCode = 254; isCached = false; hasCheckedRewrite = false; canRewrite = false; locationOfOnDuplicateKeyUpdate = -2; checkNullOrEmptyQuery(sql); hasOnDuplicateKeyUpdate = containsOnDuplicateKeyInString(sql); int startOfStatement = findStartOfStatement(sql); firstCharOfStmt = StringUtils.firstAlphaCharUc(sql, startOfStatement); isSelectQuery = 'S' == firstCharOfStmt; if(connection.versionMeetsMinimum(5, 0, 0)) serverNeedsResetBeforeEachExecution = !connection.versionMeetsMinimum(5, 0, 3); else serverNeedsResetBeforeEachExecution = !connection.versionMeetsMinimum(4, 1, 10); useAutoSlowLog = connection.getAutoSlowLog(); useTrueBoolean = connection.versionMeetsMinimum(3, 21, 23); hasLimitClause = StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1; String statementComment = connection.getStatementComment(); originalSql = statementComment != null ? "/* " + statementComment + " */ " + sql : sql; if(connection.versionMeetsMinimum(4, 1, 2)) stringTypeCode = 253; else stringTypeCode = 254; try { //关键这里,预编译sql serverPrepare(sql); } catch(SQLException sqlEx) { realClose(false, true); throw sqlEx; } catch(Exception ex) { realClose(false, true); SQLException sqlEx = SQLError.createSQLException(ex.toString(), "S1000", getExceptionInterceptor()); sqlEx.initCause(ex); throw sqlEx; } setResultSetType(resultSetType); setResultSetConcurrency(resultSetConcurrency); parameterTypes = new int[parameterCount]; } }
//预编译sql
private void serverPrepare(String sql) throws SQLException { //获取connection的互斥锁 Object obj = connection.getMutex(); JVM INSTR monitorenter ; MysqlIO mysql; //获取 MysqlIO mysql = connection.getIO(); if(connection.getAutoGenerateTestcaseScript()) dumpPrepareForTestcase(); try { long begin = 0L; if(StringUtils.startsWithIgnoreCaseAndWs(sql, "LOAD DATA")) isLoadDataQuery = true; else isLoadDataQuery = false; if(connection.getProfileSql()) begin = System.currentTimeMillis(); String characterEncoding = null; //获取connection编码信息 String connectionEncoding = connection.getEncoding(); if(!isLoadDataQuery && connection.getUseUnicode() && connectionEncoding != null) characterEncoding = connectionEncoding; //MysqlIO发送sql命令 Buffer prepareResultPacket = mysql.sendCommand(22, sql, null, false, characterEncoding, 0); if(connection.versionMeetsMinimum(4, 1, 1)) prepareResultPacket.setPosition(1); else prepareResultPacket.setPosition(0); serverStatementId = prepareResultPacket.readLong(); fieldCount = prepareResultPacket.readInt(); parameterCount = prepareResultPacket.readInt(); parameterBindings = new BindValue[parameterCount]; for(int i = 0; i < parameterCount; i++) parameterBindings[i] = new BindValue(); connection.incrementNumberOfPrepares(); if(profileSQL) eventSink.consumeEvent(new ProfilerEvent((byte)2, "", currentCatalog, connectionId, statementId, -1, System.currentTimeMillis(), mysql.getCurrentTimeNanosOrMillis() - begin, mysql.getQueryTimingUnits(), null, new Throwable(), truncateQueryToLog(sql))); if(parameterCount > 0 && connection.versionMeetsMinimum(4, 1, 2) && !mysql.isVersion(5, 0, 0)) { parameterFields = new Field[parameterCount]; Buffer metaDataPacket = mysql.readPacket(); for(int i = 0; !metaDataPacket.isLastDataPacket() && i < parameterCount; metaDataPacket = mysql.readPacket()) parameterFields[i++] = mysql.unpackField(metaDataPacket, false); } if(fieldCount > 0) { resultFields = new Field[fieldCount]; Buffer fieldPacket = mysql.readPacket(); for(int i = 0; !fieldPacket.isLastDataPacket() && i < fieldCount; fieldPacket = mysql.readPacket()) resultFields[i++] = mysql.unpackField(fieldPacket, false); } } catch(SQLException sqlEx) { if(connection.getDumpQueriesOnException()) { StringBuffer messageBuf = new StringBuffer(originalSql.length() + 32); messageBuf.append("\n\nQuery being prepared when exception was thrown:\n\n"); messageBuf.append(originalSql); sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf.toString(), getExceptionInterceptor()); } throw sqlEx; } connection.getIO().clearInputStream(); break MISSING_BLOCK_LABEL_557; Exception exception; exception; connection.getIO().clearInputStream(); throw exception; Exception exception1; exception1; throw exception1; }
来看这一句:
//MysqlIO发送sql命令
Buffer prepareResultPacket = mysql.sendCommand(22, sql, null, false, characterEncoding, 0);
//MysqlIO
final Buffer sendCommand(int command, String extraData, Buffer queryPacket, boolean skipCheck, String extraDataCharEncoding, int timeoutMillis) throws SQLException { commandCount++; enablePacketDebug = connection.getEnablePacketDebug(); readPacketSequence = 0; int oldTimeout = 0; if(timeoutMillis != 0) try { oldTimeout = mysqlConnection.getSoTimeout(); mysqlConnection.setSoTimeout(timeoutMillis); } catch(SocketException e) { throw SQLError.createCommunicationsException(connection, lastPacketSentTimeMs, lastPacketReceivedTimeMs, e, getExceptionInterceptor()); } try { Buffer buffer; try { checkForOutstandingStreamingData(); oldServerStatus = serverStatus; serverStatus = 0; hadWarnings = false; warningCount = 0; queryNoIndexUsed = false; queryBadIndexUsed = false; serverQueryWasSlow = false; if(useCompression) { int bytesLeft = mysqlInput.available(); if(bytesLeft > 0) mysqlInput.skip(bytesLeft); } try { clearInputStream(); if(queryPacket == null) { int packLength = 8 + (extraData == null ? 0 : extraData.length()) + 2; if(sendPacket == null) sendPacket = new Buffer(packLength); packetSequence = -1; readPacketSequence = 0; checkPacketSequence = true; sendPacket.clear(); sendPacket.writeByte((byte)command); if(command == 2 || command == 5 || command == 6 || command == 3 || command == 22) { if(extraDataCharEncoding == null) sendPacket.writeStringNoNull(extraData); else sendPacket.writeStringNoNull(extraData, extraDataCharEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode(), connection); } else if(command == 12) { long id = Long.parseLong(extraData); sendPacket.writeLong(id); } //发送sql Packet send(sendPacket, sendPacket.getPosition()); } else { packetSequence = -1; send(queryPacket, queryPacket.getPosition()); } } catch(SQLException sqlEx) { throw sqlEx; } catch(Exception ex) { throw SQLError.createCommunicationsException(connection, lastPacketSentTimeMs, lastPacketReceivedTimeMs, ex, getExceptionInterceptor()); } Buffer returnPacket = null; if(!skipCheck) { if(command == 23 || command == 26) { readPacketSequence = 0; packetSequenceReset = true; } returnPacket = checkErrorPacket(command); } buffer = returnPacket; } catch(IOException ioEx) { throw SQLError.createCommunicationsException(connection, lastPacketSentTimeMs, lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } return buffer; } finally { if(timeoutMillis != 0) try { mysqlConnection.setSoTimeout(oldTimeout); } catch(SocketException e) { throw SQLError.createCommunicationsException(connection, lastPacketSentTimeMs, lastPacketReceivedTimeMs, e, getExceptionInterceptor()); } } } //发送sql Packet private final void sendSplitPackets(Buffer packet) throws SQLException { try { Buffer headerPacket = splitBufRef != null ? (Buffer)splitBufRef.get() : null; if(headerPacket == null) { headerPacket = new Buffer(maxThreeBytes + 4); splitBufRef = new SoftReference(headerPacket); } int len = packet.getPosition(); int splitSize = maxThreeBytes; int originalPacketPos = 4; byte origPacketBytes[] = packet.getByteBuffer(); byte headerPacketBytes[] = headerPacket.getByteBuffer(); int packetLen; for(; len >= maxThreeBytes; len -= splitSize) { packetSequence++; headerPacket.setPosition(0); headerPacket.writeLongInt(splitSize); headerPacket.writeByte(packetSequence); System.arraycopy(origPacketBytes, originalPacketPos, headerPacketBytes, 4, splitSize); packetLen = splitSize + 4; if(!useCompression) { mysqlOutput.write(headerPacketBytes, 0, splitSize + 4); mysqlOutput.flush(); } else { headerPacket.setPosition(0); Buffer packetToSend = compressPacket(headerPacket, 4, splitSize, 4); packetLen = packetToSend.getPosition(); mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen); mysqlOutput.flush(); } originalPacketPos += splitSize; } headerPacket.clear(); headerPacket.setPosition(0); headerPacket.writeLongInt(len - 4); packetSequence++; headerPacket.writeByte(packetSequence); if(len != 0) System.arraycopy(origPacketBytes, originalPacketPos, headerPacketBytes, 4, len - 4); packetLen = len - 4; if(!useCompression) { //将数据包写入输出流 protected BufferedOutputStream mysqlOutput; mysqlOutput.write(headerPacket.getByteBuffer(), 0, len); mysqlOutput.flush(); } else { headerPacket.setPosition(0); Buffer packetToSend = compressPacket(headerPacket, 4, packetLen, 4); packetLen = packetToSend.getPosition(); mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen); mysqlOutput.flush(); } } catch(IOException ioEx) { throw SQLError.createCommunicationsException(connection, lastPacketSentTimeMs, lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } }
从上面可以看出,ServerPreparedStatement实际上就是通过MysqlIO,将sql发送到Server端。
2.
//如果server不可以预编译sql,则创建sql对应的为clientPrepareStatement
pStmt = (com.mysql.jdbc.PreparedStatement)clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
protected PreparedStatement clientPrepareStatement(String sql, int resultSetType, int resultSetConcurrency, boolean processEscapeCodesIfNeeded) throws SQLException { checkClosed(); String nativeSql = !processEscapeCodesIfNeeded || !getProcessEscapeCodesForPrepStmts() ? sql : nativeSQL(sql); com.mysql.jdbc.PreparedStatement pStmt = null; if(getCachePreparedStatements()) synchronized(cachedPreparedStatementParams) { //如果缓存,则从缓存中,获取对应的PreparedStatement.ParseInfo PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo)cachedPreparedStatementParams.get(nativeSql); if(pStmtInfo == null) { //如果缓存中,不存在ParseInfo,则创建PreparedStatement pStmt = PreparedStatement.getInstance(this, nativeSql, database); PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo(); if(parseInfo.statementLength < getPreparedStatementCacheSqlLimit()) { if(cachedPreparedStatementParams.size() >= getPreparedStatementCacheSize()) { Iterator oldestIter = cachedPreparedStatementParams.keySet().iterator(); long lruTime = 9223372036854775807L; String oldestSql = null; do { if(!oldestIter.hasNext()) break; String sqlKey = (String)oldestIter.next(); PreparedStatement.ParseInfo lruInfo = (PreparedStatement.ParseInfo)cachedPreparedStatementParams.get(sqlKey); if(lruInfo.lastUsed < lruTime) { lruTime = lruInfo.lastUsed; oldestSql = sqlKey; } } while(true); if(oldestSql != null) cachedPreparedStatementParams.remove(oldestSql); } cachedPreparedStatementParams.put(nativeSql, pStmt.getParseInfo()); } } else { pStmtInfo.lastUsed = System.currentTimeMillis(); pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql, database, pStmtInfo); } } else pStmt = PreparedStatement.getInstance(this, nativeSql, database); pStmt.setResultSetType(resultSetType); pStmt.setResultSetConcurrency(resultSetConcurrency); return pStmt; }
总结:
prepareStatement方法首先,检查连接是否关闭,关闭则直接返回;
根据server是否可以预编译sql和PreparedStatement是否为ServerPreparedStatement信息,
来确定返回的prepareStatement是ServerPreparedStatement还是com.mysql.jdbc.PreparedStatement,server可以预编译sql,且PreparedStatement为ServerPreparedStatement则返回的是ServerPreparedStatement
否则返回的是com.mysql.jdbc.PreparedStatement。ServerPreparedStatement实际上就是通过MysqlIO,将sql发送到Server端。
//LRUCache,LRUCache实际上是一个Map
public class LRUCache extends LinkedHashMap { public LRUCache(int maxSize) { super(maxSize); maxElements = maxSize; } //关键在这个方法,当Map,put或putAll时,当添加元素后,Map的size大于其maxSize,调用 //此方法,判断是否需要移除Eldest元素 protected boolean removeEldestEntry(java.util.Map.Entry eldest) { return size() > maxElements; } private static final long serialVersionUID = 1L; protected int maxElements; }
//MysqlIO class MysqlIO { private static final int UTF8_CHARSET_INDEX = 33; private static final String CODE_PAGE_1252 = "Cp1252"; protected static final int NULL_LENGTH = -1; protected static final int COMP_HEADER_LENGTH = 3; protected static final int MIN_COMPRESS_LEN = 50; protected static final int HEADER_LENGTH = 4; protected static final int AUTH_411_OVERHEAD = 33; private static int maxBufferSize = 65535; private static final int CLIENT_COMPRESS = 32; protected static final int CLIENT_CONNECT_WITH_DB = 8; private static final int CLIENT_FOUND_ROWS = 2; private static final int CLIENT_LOCAL_FILES = 128; private static final int CLIENT_LONG_FLAG = 4; private static final int CLIENT_LONG_PASSWORD = 1; private static final int CLIENT_PROTOCOL_41 = 512; private static final int CLIENT_INTERACTIVE = 1024; protected static final int CLIENT_SSL = 2048; private static final int CLIENT_TRANSACTIONS = 8192; protected static final int CLIENT_RESERVED = 16384; protected static final int CLIENT_SECURE_CONNECTION = 32768; private static final int CLIENT_MULTI_QUERIES = 65536; private static final int CLIENT_MULTI_RESULTS = 131072; private static final int SERVER_STATUS_IN_TRANS = 1; private static final int SERVER_STATUS_AUTOCOMMIT = 2; static final int SERVER_MORE_RESULTS_EXISTS = 8; private static final int SERVER_QUERY_NO_GOOD_INDEX_USED = 16; private static final int SERVER_QUERY_NO_INDEX_USED = 32; private static final int SERVER_QUERY_WAS_SLOW = 2048; private static final int SERVER_STATUS_CURSOR_EXISTS = 64; private static final String FALSE_SCRAMBLE = "xxxxxxxx"; protected static final int MAX_QUERY_SIZE_TO_LOG = 1024; protected static final int MAX_QUERY_SIZE_TO_EXPLAIN = 1048576; protected static final int INITIAL_PACKET_SIZE = 1024; private static String jvmPlatformCharset = null; protected static final String ZERO_DATE_VALUE_MARKER = "0000-00-00"; protected static final String ZERO_DATETIME_VALUE_MARKER = "0000-00-00 00:00:00"; private static final int MAX_PACKET_DUMP_LENGTH = 1024; private boolean packetSequenceReset; protected int serverCharsetIndex; private Buffer reusablePacket; private Buffer sendPacket; private Buffer sharedSendPacket; protected BufferedOutputStream mysqlOutput; protected ConnectionImpl connection;//Mysql connection private Deflater deflater; protected InputStream mysqlInput;//mysql输入流 private LinkedList packetDebugRingBuffer; private RowData streamingData; protected Socket mysqlConnection;//mysql socket private SocketFactory socketFactory;// mysql socket的工场 private SoftReference loadFileBufRef; private SoftReference splitBufRef; protected String host;//host protected String seed; private String serverVersion; private String socketFactoryClassName; private byte packetHeaderBuf[]; private boolean colDecimalNeedsBump; private boolean hadWarnings; private boolean has41NewNewProt; private boolean hasLongColumnInfo; private boolean isInteractiveClient; private boolean logSlowQueries; private boolean platformDbCharsetMatches; private boolean profileSql; private boolean queryBadIndexUsed; private boolean queryNoIndexUsed; private boolean serverQueryWasSlow; private boolean use41Extensions; private boolean useCompression; private boolean useNewLargePackets; private boolean useNewUpdateCounts; private byte packetSequence; private byte readPacketSequence; private boolean checkPacketSequence; private byte protocolVersion; private int maxAllowedPacket; protected int maxThreeBytes; protected int port; protected int serverCapabilities; private int serverMajorVersion; private int serverMinorVersion; private int oldServerStatus; private int serverStatus; private int serverSubMinorVersion; private int warningCount; protected long clientParam; protected long lastPacketSentTimeMs; protected long lastPacketReceivedTimeMs; private boolean traceProtocol; private boolean enablePacketDebug; private Calendar sessionCalendar; private boolean useConnectWithDb; private boolean needToGrabQueryFromPacket; private boolean autoGenerateTestcaseScript; private long threadId; private boolean useNanosForElapsedTime; private long slowQueryThreshold; private String queryTimingUnits; private boolean useDirectRowUnpack; private int useBufferRowSizeThreshold; private int commandCount; private List statementInterceptors; private ExceptionInterceptor exceptionInterceptor; private int statementExecutionDepth; private boolean useAutoSlowLog; static { OutputStreamWriter outWriter = null; try { outWriter = new OutputStreamWriter(new ByteArrayOutputStream()); jvmPlatformCharset = outWriter.getEncoding(); } finally { try { if(outWriter != null) outWriter.close(); } catch(IOException ioEx) { } } } //MysqlIO构造 public MysqlIO(String host, int port, Properties props, String socketFactoryClassName, ConnectionImpl conn, int socketTimeout, int useBufferRowSizeThreshold) throws IOException, SQLException { packetSequenceReset = false; reusablePacket = null; sendPacket = null; sharedSendPacket = null; mysqlOutput = null; deflater = null; mysqlInput = null; packetDebugRingBuffer = null; streamingData = null; mysqlConnection = null; socketFactory = null; this.host = null; serverVersion = null; this.socketFactoryClassName = null; packetHeaderBuf = new byte[4]; colDecimalNeedsBump = false; hadWarnings = false; has41NewNewProt = false; hasLongColumnInfo = false; isInteractiveClient = false; logSlowQueries = false; platformDbCharsetMatches = true; profileSql = false; queryBadIndexUsed = false; queryNoIndexUsed = false; serverQueryWasSlow = false; use41Extensions = false; useCompression = false; useNewLargePackets = false; useNewUpdateCounts = false; packetSequence = 0; readPacketSequence = -1; checkPacketSequence = false; protocolVersion = 0; maxAllowedPacket = 1048576; maxThreeBytes = 16581375; this.port = 3306; serverMajorVersion = 0; serverMinorVersion = 0; oldServerStatus = 0; serverStatus = 0; serverSubMinorVersion = 0; warningCount = 0; clientParam = 0L; lastPacketSentTimeMs = 0L; lastPacketReceivedTimeMs = 0L; traceProtocol = false; enablePacketDebug = false; useDirectRowUnpack = true; commandCount = 0; statementExecutionDepth = 0; connection = conn; if(connection.getEnablePacketDebug()) packetDebugRingBuffer = new LinkedList(); traceProtocol = connection.getTraceProtocol(); useAutoSlowLog = connection.getAutoSlowLog(); this.useBufferRowSizeThreshold = useBufferRowSizeThreshold; useDirectRowUnpack = connection.getUseDirectRowUnpack(); logSlowQueries = connection.getLogSlowQueries(); reusablePacket = new Buffer(1024); sendPacket = new Buffer(1024); this.port = port; this.host = host; this.socketFactoryClassName = socketFactoryClassName; //创建socket的工场 socketFactory = createSocketFactory(); exceptionInterceptor = connection.getExceptionInterceptor(); try { //从socket的工场获取连接 mysqlConnection = socketFactory.connect(this.host, this.port, props); if(socketTimeout != 0) try { mysqlConnection.setSoTimeout(socketTimeout); } catch(Exception ex) { } //握手 mysqlConnection = socketFactory.beforeHandshake(); if(connection.getUseReadAheadInput()) mysqlInput = new ReadAheadInputStream(mysqlConnection.getInputStream(), 16384, connection.getTraceProtocol(), connection.getLog()); else if(connection.useUnbufferedInput()) //从mysqlConnection获取输入流 mysqlInput = mysqlConnection.getInputStream(); else mysqlInput = new BufferedInputStream(mysqlConnection.getInputStream(), 16384); //初始化mysqlOutput输出流 mysqlOutput = new BufferedOutputStream(mysqlConnection.getOutputStream(), 16384); isInteractiveClient = connection.getInteractiveClient(); profileSql = connection.getProfileSql(); sessionCalendar = Calendar.getInstance(); autoGenerateTestcaseScript = connection.getAutoGenerateTestcaseScript(); needToGrabQueryFromPacket = profileSql || logSlowQueries || autoGenerateTestcaseScript; if(connection.getUseNanosForElapsedTime() && Util.nanoTimeAvailable()) { useNanosForElapsedTime = true; queryTimingUnits = Messages.getString("Nanoseconds"); } else { queryTimingUnits = Messages.getString("Milliseconds"); } if(connection.getLogSlowQueries()) calculateSlowQueryThreshold(); } catch(IOException ioEx) { throw SQLError.createCommunicationsException(connection, 0L, 0L, ioEx, getExceptionInterceptor()); } } }
发表评论
-
Mysql PreparedStatement 批处理
2016-12-06 18:09 1384JDBC驱动初始化-Mysql:http://donald-d ... -
MySQL ServerPreparedStatement查询
2016-12-06 14:42 1291JDBC驱动初始化-Mysql:http://donald-d ... -
MysqlSQL PreparedStatement的查询
2016-12-06 11:40 2028JDBC驱动初始化-Mysql:http://donald-d ... -
ConnectionImp创建MysqlIO
2016-12-05 19:01 1020JDBC驱动初始化-Mysql:http://donald-d ... -
Mysql主从复制读写分离连接的获取
2016-12-01 08:43 1161JDBC驱动初始化-Mysql:http://donald-d ... -
Mysql负载均衡连接的获取
2016-12-01 08:38 1323Java动态代理:http://www.cnblogs.com ... -
JDBC连接的获取
2016-11-30 12:44 2933JDBC驱动初始化-Mysql:http://donald-d ... -
JDBC驱动初始化-Mysql
2016-11-30 12:41 3049JDBC驱动初始化-Mysql:http://donald-d ... -
mysql 存储过程
2016-07-17 14:49 898存储过程基础:http://sishuok.com/forum ... -
java.sql.Date,java.util.Date,java.sql.Timestamp的区别
2016-07-17 11:50 878java.sql.Date,jdbc映射数据库中的date类型 ... -
JDBC PreparedStatement 的用法
2016-07-15 17:27 892import java.sql.Connection; im ...
相关推荐
MySQL 预编译功能是指在执行 SQL 语句之前,对 SQL 语句进行编译和优化,以提高执行效率。在 MySQL 中,预编译功能可以通过使用 Prepare 语句来实现。 预编译功能的优点是可以减少 SQL 语句的执行时间,因为在执行 ...
2. **预编译查询**:DBI提供了`prepare`方法来预编译SQL语句,然后用`execute`方法多次执行。这可以显著提高性能,尤其是在反复执行相同查询时: ```perl my $sth = $dbh->prepare('SELECT * FROM table WHERE id ...
MySQL预编译是一种提高数据库操作效率的技术,尤其在处理大量重复SQL语句时效果显著。预编译的主要目的是减少语法检查和编译的开销,从而提升数据库的性能。本文将深入探讨MySQL预编译的概念、好处、执行过程以及...
MySQL的预编译功能是一种优化技术,主要用于提高数据库操作的性能,特别是在执行大量重复的SQL语句时。预编译的核心思想是将SQL语句的语法检查和编译过程提前到第一次执行时完成,之后只需替换不同的参数即可,避免...
MySqlFrm.exe是c#版本的frm转sql工具,需要.net 4.0与mysql环境,CMD命令行如下: mysqlfrm <username> <password> <port> 例如: mysqlfrm root pass 3306 c:\dbcopy 会将c:\dbcopy目录下所有的frm转换为...
安装这个工具后,你可以通过解析MySQL的Yacc(YACC:Yet Another Compiler-Compiler)文件来生成C代码,这些代码是MySQL解析SQL语句所必需的。 接下来,我们提到的是`Perl`,在这里具体为`ActivePerl-5.16.3.1604-...
MySQL是一种广泛使用的开源关系型数据库管理系统(RDBMS),它基于结构化查询语言(SQL)。在Linux环境下,如果你想要从源代码进行编译安装MySQL,这通常是为了获得更高的定制性或者适应特定系统环境。以下是对...
在本文中,我们将深入探讨如何在Qt环境中编译MySQL驱动,以便在Qt应用程序中与MySQL数据库进行交互。首先,我们要明确的是,这个过程通常适用于Qt 5.2及其更高版本,因为这是支持编译MySQL驱动的最低要求。在这个...
在本文中,我们将深入探讨如何在Qt环境中编译MySQL驱动,以便在Qt应用程序中与MySQL数据库进行交互。这个过程可能对新手来说有些复杂,因为网上的教程可能存在误导或不完整的情况。但不用担心,我们将逐步解释整个...
这里使用了`-qt-sql-mysql`选项来静态编译MySQL驱动。 3. 执行`make`和`make install`,这将生成包含MySQL驱动的QT库文件。 接下来是ARM开发板的QT MySQL驱动编译: 1. 对于嵌入式版本,因为需要交叉编译,所以...
在上述示例中,`PreparedStatement`预编译了SQL语句,提高了执行效率并降低了SQL注入的风险。`ResultSet`对象则用于存储查询结果,通过遍历结果集来获取数据。 总结来说,SQL2005和MySQL是两种不同的数据库系统,...
这里提到的“erlang_mysql编译好了”可能是指已经成功编译了这样的库,它提供了一个Erlang应用程序,使得Erlang进程可以直接与MySQL服务器通信。这个过程通常涉及以下步骤: 1. **获取源代码**:你需要找到Erlang ...
标题“SQL.rar_labview mysql_mysql labview_sql”和描述“在labview中实现数据库MySQL调用的节点函数...在实际项目中,确保遵循最佳实践,如使用预编译的SQL语句防止SQL注入,以及适时关闭数据库连接以优化资源利用。
- 存储过程(Stored Procedure):预编译的SQL语句集合,可以提高性能并简化复杂操作。 - 触发器(Trigger):自动执行的数据库操作,基于特定的事件(如INSERT、UPDATE或DELETE)。 通过“www.pudn.com.txt”文件...
1. **使用预编译语句和参数化查询**:预编译语句可以防止SQL注入,因为它们将SQL语句和数据分开处理,避免了恶意代码的执行。 2. **输入验证和数据清理**:对所有用户输入进行验证,确保只接受预期格式的数据,并对...
7. **存储过程与函数**: 存储过程是一组预编译的SQL语句,可提高代码复用性和执行效率。函数则是在查询中可以直接调用的预定义操作,如内置数学函数、字符串函数和日期时间函数。 8. **触发器**: 触发器是响应特定...
8. **SQL标准的兼容性**:MySQL 5.7在遵循SQL标准方面取得了显著进步,例如支持窗口函数和 Common Table Expressions(CTE),使SQL语句编写更为简洁和强大。 综上所述,MySQL 5.7.23 源码编译包带Boost是一个全面...
为了优化性能,可能还应用了预编译的PreparedStatement,以防止SQL注入攻击。 此外,项目可能还包括异常处理、日志记录、安全性考虑等多方面的实践。例如,对敏感信息如密码进行加密存储,使用HTTPS协议确保通信...