- 浏览: 980168 次
文章分类
- 全部博客 (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
前面几讲,说过mysql的连接获取,MysqlIO,今天来看一下MySQL的PreparedStatement查询
//ConnectionImpl
来看PreparedStatement的构造
//PreparedStatement
构造PreparedStatement完毕,来看一下,如何查询
来看没有分页语句的查询executeInternal
我们来看一下这一段都做了些什么?
//StatementImpl
//创建Statement
//连接定时任务执行器Timer,等待timeoutInMillis毫秒后,执行查询定时任务timeoutTask
ConnectionImpl.getCancelTimer().schedule(timeoutTask, timeoutInMillis);
//ConnectionImpl
从上面这一段可以看出,如果延时查询的话,就创建StatementImpl.CancelTask(TimeTask)定时任务,并由ConnectionImpl的cancelTimer(Timer)去调度。
回到executeInternal方法,
来看执行查询,返回结果集,这个时调用ConnectionImpl的execSQL
//ConnectionImpl
来看MysqlIO执行查询
//MysqlIO
总结:
PreparedStatement执行查询,实际上是通过ConnectionImpl的execSQL,而ConnectionImpl的执行查询,实际上是通过MysqlIO,MysqlIO执行查询,就是将Sql查询,组成Mysql的查询包,通过socket的发送给Server,Server返回查询结果缓存区,然后MysqlIO将结果缓存区转换为ResultSetInternalMethods(ResultSetImpl),就是我们需要的结果集,即ResultSet。
//ResultSetInternalMethods
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
前面几讲,说过mysql的连接获取,MysqlIO,今天来看一下MySQL的PreparedStatement查询
//ConnectionImpl
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 pStmtInfo = (PreparedStatement.ParseInfo)cachedPreparedStatementParams.get(nativeSql); if(pStmtInfo == null) { 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 //如果没有缓存,获取PreparedStatement实例 pStmt = PreparedStatement.getInstance(this, nativeSql, database); pStmt.setResultSetType(resultSetType); pStmt.setResultSetConcurrency(resultSetConcurrency); return pStmt; }
来看PreparedStatement的构造
//PreparedStatement
public class PreparedStatement extends StatementImpl implements java.sql.PreparedStatement { protected static PreparedStatement getInstance(ConnectionImpl conn, String sql, String catalog) throws SQLException { if(!Util.isJdbc4()) return new PreparedStatement(conn, sql, catalog); else return (PreparedStatement)Util.handleNewInstance(JDBC_4_PSTMT_3_ARG_CTOR, new Object[] { conn, sql, catalog }, conn.getExceptionInterceptor()); } public PreparedStatement(ConnectionImpl conn, String sql, String catalog) throws SQLException { super(conn, catalog); batchHasPlainStatements = false; dbmd = null; firstCharOfStmt = '\0'; hasLimitClause = false; isLoadDataQuery = false; isNull = null; isStream = null; numberOfExecutions = 0; originalSql = null; parameterStreams = null; //参数值 parameterValues = (byte[][])null; //参数类型 parameterTypes = null; staticSqlStrings = (byte[][])null; streamConvertBuf = new byte[4096]; streamLengths = null; tsdf = null; useTrueBoolean = false; hasCheckedForRewrite = false; canRewrite = false; compensateForOnDuplicateKeyUpdate = false; batchCommandIndex = -1; if(sql == null) throw SQLError.createSQLException(Messages.getString("PreparedStatement.0"), "S1009", getExceptionInterceptor()); originalSql = sql; if(originalSql.startsWith("/* ping */")) doPingInstead = true; else doPingInstead = false; //获取数据库MetaData dbmd = connection.getMetaData(); useTrueBoolean = connection.versionMeetsMinimum(3, 21, 23); //构建Statement的 parseInfo = new ParseInfo(sql, connection, dbmd, charEncoding, charConverter); initializeFromParseInfo(); compensateForOnDuplicateKeyUpdate = connection.getCompensateOnDuplicateKeyUpdateCounts(); if(conn.getRequiresEscapingEncoder()) charsetEncoder = Charset.forName(conn.getEncoding()).newEncoder(); } }
构造PreparedStatement完毕,来看一下,如何查询
public ResultSet executeQuery() throws SQLException { checkClosed(); ConnectionImpl locallyScopedConn = connection; checkForDml(originalSql, firstCharOfStmt); CachedResultSetMetaData cachedMetadata = null; synchronized(locallyScopedConn.getMutex()) { clearWarnings(); boolean doStreaming = createStreamingResultSet(); batchedGeneratedKeys = null; if(doStreaming && connection.getNetTimeoutForStreamingResults() > 0) locallyScopedConn.execSQL(this, "SET net_write_timeout=" + connection.getNetTimeoutForStreamingResults(), -1, null, 1003, 1007, false, currentCatalog, null, false); Buffer sendPacket = fillSendPacket(); if(results != null && !connection.getHoldResultsOpenOverStatementClose() && !holdResultsOpenOverClose) results.realClose(false); String oldCatalog = null; if(!locallyScopedConn.getCatalog().equals(currentCatalog)) { oldCatalog = locallyScopedConn.getCatalog(); locallyScopedConn.setCatalog(currentCatalog); } if(locallyScopedConn.getCacheResultSetMetadata()) cachedMetadata = locallyScopedConn.getCachedMetaData(originalSql); Field metadataFromCache[] = null; if(cachedMetadata != null) metadataFromCache = cachedMetadata.fields; if(locallyScopedConn.useMaxRows()) { if(hasLimitClause) { //没有分页语句的查询 results = executeInternal(maxRows, sendPacket, createStreamingResultSet(), true, metadataFromCache, false); } else { if(maxRows <= 0) executeSimpleNonQuery(locallyScopedConn, "SET OPTION SQL_SELECT_LIMIT=DEFAULT"); else executeSimpleNonQuery(locallyScopedConn, "SET OPTION SQL_SELECT_LIMIT=" + maxRows); results = executeInternal(-1, sendPacket, doStreaming, true, metadataFromCache, false); if(oldCatalog != null) connection.setCatalog(oldCatalog); } } else { results = executeInternal(-1, sendPacket, doStreaming, true, metadataFromCache, false); } if(oldCatalog != null) locallyScopedConn.setCatalog(oldCatalog); if(cachedMetadata != null) locallyScopedConn.initializeResultsMetadataFromCache(originalSql, cachedMetadata, results); else if(locallyScopedConn.getCacheResultSetMetadata()) locallyScopedConn.initializeResultsMetadataFromCache(originalSql, null, results); } lastInsertId = results.getUpdateID(); return results; }
来看没有分页语句的查询executeInternal
protected ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly, Field metadataFromCache[], boolean isBatch) throws SQLException { ConnectionImpl locallyScopedConnection; resetCancelledState(); locallyScopedConnection = connection; numberOfExecutions++; if(!doPingInstead) break MISSING_BLOCK_LABEL_36; doPingInstead(); return results; StatementImpl.CancelTask timeoutTask = null; ResultSetInternalMethods rs; if(locallyScopedConnection.getEnableQueryTimeouts() && timeoutInMillis != 0 && locallyScopedConnection.versionMeetsMinimum(5, 0, 0)) { timeoutTask = new StatementImpl.CancelTask(this, this); //连接定时任务执行器Timer,等待timeoutInMillis毫秒后,执行查询定时任务timeoutTask ConnectionImpl.getCancelTimer().schedule(timeoutTask, timeoutInMillis); } //执行查询,并返回结果集 rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket, resultSetType, resultSetConcurrency, createStreamingResultSet, currentCatalog, metadataFromCache, isBatch); if(timeoutTask != null) { timeoutTask.cancel(); if(timeoutTask.caughtWhileCancelling != null) throw timeoutTask.caughtWhileCancelling; timeoutTask = null; } synchronized(cancelTimeoutMutex) { if(wasCancelled) { SQLException cause = null; if(wasCancelledByTimeout) cause = new MySQLTimeoutException(); else cause = new MySQLStatementCancelledException(); resetCancelledState(); throw cause; } } if(timeoutTask != null) timeoutTask.cancel(); break MISSING_BLOCK_LABEL_242; Exception exception1; exception1; if(timeoutTask != null) timeoutTask.cancel(); throw exception1; return rs; NullPointerException npe; npe; checkClosed(); throw npe; }
我们来看一下这一段都做了些什么?
if(locallyScopedConnection.getEnableQueryTimeouts() && timeoutInMillis != 0 && locallyScopedConnection.versionMeetsMinimum(5, 0, 0)) { timeoutTask = new StatementImpl.CancelTask(this, this); //连接定时任务执行器Timer,等待timeoutInMillis毫秒后,执行查询定时任务timeoutTask ConnectionImpl.getCancelTimer().schedule(timeoutTask, timeoutInMillis); }
//StatementImpl
public class StatementImpl implements com.mysql.jdbc.Statement { class CancelTask extends TimerTask { public void run() { Thread cancelThread = new Thread() { public void run() { com.mysql.jdbc.Connection cancelConn = null; Statement cancelStmt = null; try { synchronized(cancelTimeoutMutex) { //复制connection cancelConn = connection.duplicate(); //创建Statement cancelStmt = cancelConn.createStatement(); cancelStmt.execute("KILL QUERY " + connectionId); toCancel.wasCancelled = true; toCancel.wasCancelledByTimeout = true; } } catch(SQLException sqlEx) { caughtWhileCancelling = sqlEx; } catch(NullPointerException npe) { } finally { if(cancelStmt != null) try { cancelStmt.close(); } catch(SQLException sqlEx) { throw new RuntimeException(sqlEx.toString()); } if(cancelConn != null) try { cancelConn.close(); } catch(SQLException sqlEx) { throw new RuntimeException(sqlEx.toString()); } } } }; cancelThread.start(); } long connectionId; SQLException caughtWhileCancelling; StatementImpl toCancel; CancelTask(StatementImpl cancellee) throws SQLException { connectionId = 0L; caughtWhileCancelling = null; connectionId = connection.getIO().getThreadId(); toCancel = cancellee; } } }
//创建Statement
cancelStmt = cancelConn.createStatement();
//ConnectionImpl public Statement createStatement() throws SQLException { return createStatement(1003, 1007); } public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { checkClosed(); StatementImpl stmt = new StatementImpl(this, database); stmt.setResultSetType(resultSetType); stmt.setResultSetConcurrency(resultSetConcurrency); return stmt; }
//连接定时任务执行器Timer,等待timeoutInMillis毫秒后,执行查询定时任务timeoutTask
ConnectionImpl.getCancelTimer().schedule(timeoutTask, timeoutInMillis);
//ConnectionImpl
protected static Timer getCancelTimer() { //private static Timer cancelTimer; return cancelTimer; }
从上面这一段可以看出,如果延时查询的话,就创建StatementImpl.CancelTask(TimeTask)定时任务,并由ConnectionImpl的cancelTimer(Timer)去调度。
回到executeInternal方法,
来看执行查询,返回结果集,这个时调用ConnectionImpl的execSQL
//ConnectionImpl
ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, Buffer packet, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Field cachedMetadata[], boolean isBatch) throws SQLException { Object obj = mutex; JVM INSTR monitorenter ; long queryStartTime; int endOfQueryPacketPosition; queryStartTime = 0L; endOfQueryPacketPosition = 0; if(packet != null) endOfQueryPacketPosition = packet.getPosition(); if(getGatherPerformanceMetrics()) queryStartTime = System.currentTimeMillis(); lastQueryFinishedTime = 0L; if(!failedOver || !autoCommit || isBatch || !shouldFallBack() || executingFailoverReconnect) break MISSING_BLOCK_LABEL_151; executingFailoverReconnect = true; //创建MysqlIO,这个我们在前面ServerPrepareStatement中讲过 createNewIO(true); String connectedHost = io.getHost(); if(connectedHost != null && hostList.get(0).equals(connectedHost)) { failedOver = false; queriesIssuedFailedOver = 0L; setReadOnlyInternal(false); } if((getHighAvailability() || failedOver) && (autoCommit || getAutoReconnectForPools()) && needsPing && !isBatch) try { pingInternal(false, 0); needsPing = false; } catch(Exception Ex) { createNewIO(true); } ResultSetInternalMethods resultsetinternalmethods1; if(packet != null) break MISSING_BLOCK_LABEL_267; String encoding = null; if(getUseUnicode()) encoding = getEncoding(); //关键在这一句MysqlIO执行查询 resultsetinternalmethods1 = io.sqlQueryDirect(callingStatement, sql, encoding, null, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata); return resultsetinternalmethods1; ResultSetInternalMethods resultsetinternalmethods; try { resultsetinternalmethods = io.sqlQueryDirect(callingStatement, null, null, packet, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata); } return resultsetinternalmethods; }
来看MysqlIO执行查询
//MysqlIO
final ResultSetInternalMethods sqlQueryDirect(StatementImpl callingStatement, String query, String characterEncoding, Buffer queryPacket, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Field cachedMetadata[]) throws Exception { statementExecutionDepth++; //返回结果集 ResultSetInternalMethods resultsetinternalmethods; if(statementInterceptors == null) break MISSING_BLOCK_LABEL_47; //拦截器处理 ResultSetInternalMethods interceptedResults = invokeStatementInterceptorsPre(query, callingStatement); if(interceptedResults == null) break MISSING_BLOCK_LABEL_47; resultsetinternalmethods = interceptedResults; statementExecutionDepth--; return resultsetinternalmethods; ResultSetInternalMethods resultsetinternalmethods1; long queryStartTime = 0L; long queryEndTime = 0L; if(query != null) { int packLength = 5 + query.length() * 2 + 2; String statementComment = connection.getStatementComment(); byte commentAsBytes[] = null; if(statementComment != null) { commentAsBytes = StringUtils.getBytes(statementComment, null, characterEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode(), getExceptionInterceptor()); packLength += commentAsBytes.length; packLength += 6; } if(sendPacket == null) sendPacket = new Buffer(packLength); else sendPacket.clear(); sendPacket.writeByte((byte)3); if(commentAsBytes != null) { //将注释添加的查询包中 sendPacket.writeBytesNoNull(Constants.SLASH_STAR_SPACE_AS_BYTES); sendPacket.writeBytesNoNull(commentAsBytes); sendPacket.writeBytesNoNull(Constants.SPACE_STAR_SLASH_SPACE_AS_BYTES); } if(characterEncoding != null) { //如果有编码信息,则将查询编码后,组装到包中 if(platformDbCharsetMatches) sendPacket.writeStringNoNull(query, characterEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode(), connection); else if(StringUtils.startsWithIgnoreCaseAndWs(query, "LOAD DATA")) sendPacket.writeBytesNoNull(query.getBytes()); else sendPacket.writeStringNoNull(query, characterEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode(), connection); } else { sendPacket.writeStringNoNull(query); } queryPacket = sendPacket; } byte queryBuf[] = null; int oldPacketPosition = 0; if(needToGrabQueryFromPacket) { queryBuf = queryPacket.getByteBuffer(); oldPacketPosition = queryPacket.getPosition(); queryStartTime = getCurrentTimeNanosOrMillis(); } if(autoGenerateTestcaseScript) { String testcaseQuery = null; if(query != null) testcaseQuery = query; else testcaseQuery = new String(queryBuf, 5, oldPacketPosition - 5); StringBuffer debugBuf = new StringBuffer(testcaseQuery.length() + 32); connection.generateConnectionCommentBlock(debugBuf); debugBuf.append(testcaseQuery); debugBuf.append(';'); connection.dumpTestcaseQuery(debugBuf.toString()); } //MysqlIO发送查询包到Server,获取返回结果 Buffer resultPacket = sendCommand(3, null, queryPacket, false, null, 0); long fetchBeginTime = 0L; long fetchEndTime = 0L; String profileQueryToLog = null; boolean queryWasSlow = false; if(profileSql || logSlowQueries) { queryEndTime = System.currentTimeMillis(); boolean shouldExtractQuery = false; if(profileSql) shouldExtractQuery = true; else if(logSlowQueries) { long queryTime = queryEndTime - queryStartTime; boolean logSlow = false; if(useAutoSlowLog) { logSlow = queryTime > (long)connection.getSlowQueryThresholdMillis(); } else { logSlow = connection.isAbonormallyLongQuery(queryTime); connection.reportQueryTime(queryTime); } if(logSlow) { shouldExtractQuery = true; queryWasSlow = true; } } if(shouldExtractQuery) { boolean truncated = false; int extractPosition = oldPacketPosition; if(oldPacketPosition > connection.getMaxQuerySizeToLog()) { extractPosition = connection.getMaxQuerySizeToLog() + 5; truncated = true; } profileQueryToLog = new String(queryBuf, 5, extractPosition - 5); if(truncated) profileQueryToLog = profileQueryToLog + Messages.getString("MysqlIO.25"); } fetchBeginTime = queryEndTime; } //从中resultPacket,获取返回结果 ResultSetInternalMethods rs = readAllResults(callingStatement, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, resultPacket, false, -1L, cachedMetadata); if(queryWasSlow && !serverQueryWasSlow) { StringBuffer mesgBuf = new StringBuffer(48 + profileQueryToLog.length()); mesgBuf.append(Messages.getString("MysqlIO.SlowQuery", new Object[] { new Long(slowQueryThreshold), queryTimingUnits, new Long(queryEndTime - queryStartTime) })); mesgBuf.append(profileQueryToLog); ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(connection); eventSink.consumeEvent(new ProfilerEvent((byte)6, "", catalog, connection.getId(), callingStatement == null ? 999 : callingStatement.getId(), ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), (int)(queryEndTime - queryStartTime), queryTimingUnits, null, new Throwable(), mesgBuf.toString())); if(connection.getExplainSlowQueries()) if(oldPacketPosition < 1048576) explainSlowQuery(queryPacket.getBytes(5, oldPacketPosition - 5), profileQueryToLog); else connection.getLog().logWarn(Messages.getString("MysqlIO.28") + 1048576 + Messages.getString("MysqlIO.29")); } if(logSlowQueries) { ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(connection); if(queryBadIndexUsed) eventSink.consumeEvent(new ProfilerEvent((byte)6, "", catalog, connection.getId(), callingStatement == null ? 999 : callingStatement.getId(), ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), queryEndTime - queryStartTime, queryTimingUnits, null, new Throwable(), Messages.getString("MysqlIO.33") + profileQueryToLog)); if(queryNoIndexUsed) eventSink.consumeEvent(new ProfilerEvent((byte)6, "", catalog, connection.getId(), callingStatement == null ? 999 : callingStatement.getId(), ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), queryEndTime - queryStartTime, queryTimingUnits, null, new Throwable(), Messages.getString("MysqlIO.35") + profileQueryToLog)); if(serverQueryWasSlow) eventSink.consumeEvent(new ProfilerEvent((byte)6, "", catalog, connection.getId(), callingStatement == null ? 999 : callingStatement.getId(), ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), queryEndTime - queryStartTime, queryTimingUnits, null, new Throwable(), Messages.getString("MysqlIO.ServerSlowQuery") + profileQueryToLog)); } if(profileSql) { fetchEndTime = getCurrentTimeNanosOrMillis(); ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(connection); eventSink.consumeEvent(new ProfilerEvent((byte)3, "", catalog, connection.getId(), callingStatement == null ? 999 : callingStatement.getId(), ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), queryEndTime - queryStartTime, queryTimingUnits, null, new Throwable(), profileQueryToLog)); eventSink.consumeEvent(new ProfilerEvent((byte)5, "", catalog, connection.getId(), callingStatement == null ? 999 : callingStatement.getId(), ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), fetchEndTime - fetchBeginTime, queryTimingUnits, null, new Throwable(), null)); } if(hadWarnings) scanForAndThrowDataTruncation(); if(statementInterceptors != null) { ResultSetInternalMethods interceptedResults = invokeStatementInterceptorsPost(query, callingStatement, rs); if(interceptedResults != null) rs = interceptedResults; } resultsetinternalmethods1 = rs; statementExecutionDepth--; return resultsetinternalmethods1; }
//从缓冲区,去除结果集 ResultSetImpl readAllResults(StatementImpl callingStatement, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Buffer resultPacket, boolean isBinaryEncoded, long preSentColumnCount, Field metadataFromCache[]) throws SQLException { resultPacket.setPosition(resultPacket.getPosition() - 1); ResultSetImpl topLevelResultSet = readResultsForQueryOrUpdate(callingStatement, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, resultPacket, isBinaryEncoded, preSentColumnCount, metadataFromCache); ResultSetImpl currentResultSet = topLevelResultSet; boolean checkForMoreResults = (clientParam & 131072L) != 0L; boolean serverHasMoreResults = (serverStatus & 8) != 0; if(serverHasMoreResults && streamResults) { if(topLevelResultSet.getUpdateCount() != -1L) tackOnMoreStreamingResults(topLevelResultSet); reclaimLargeReusablePacket(); return topLevelResultSet; } for(boolean moreRowSetsExist = checkForMoreResults & serverHasMoreResults; moreRowSetsExist; moreRowSetsExist = (serverStatus & 8) != 0) { Buffer fieldPacket = checkErrorPacket(); fieldPacket.setPosition(0); //读取结果集 ResultSetImpl newResultSet = readResultsForQueryOrUpdate(callingStatement, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, fieldPacket, isBinaryEncoded, preSentColumnCount, metadataFromCache); currentResultSet.setNextResultSet(newResultSet); currentResultSet = newResultSet; } if(!streamResults) clearInputStream(); reclaimLargeReusablePacket(); return topLevelResultSet; }
总结:
PreparedStatement执行查询,实际上是通过ConnectionImpl的execSQL,而ConnectionImpl的执行查询,实际上是通过MysqlIO,MysqlIO执行查询,就是将Sql查询,组成Mysql的查询包,通过socket的发送给Server,Server返回查询结果缓存区,然后MysqlIO将结果缓存区转换为ResultSetInternalMethods(ResultSetImpl),就是我们需要的结果集,即ResultSet。
public class ResultSetImpl implements ResultSetInternalMethods { public float getFloat(int columnIndex) throws SQLException { if(!isBinaryEncoded) { String val = null; //获取columnIndex对应的String值 val = getString(columnIndex); //将String转换为Float return getFloatFromString(val, columnIndex); } else { return getNativeFloat(columnIndex); } } public float getFloat(String columnName) throws SQLException { return getFloat(findColumn(columnName)); } //获取columnIndex对应的String值 public String getString(int columnIndex) throws SQLException { String stringVal = getStringInternal(columnIndex, true); if(padCharsWithSpace && stringVal != null) { Field f = fields[columnIndex - 1]; if(f.getMysqlType() == 254) { int fieldLength = (int)f.getLength() / f.getMaxBytesPerCharacter(); int currentLength = stringVal.length(); if(currentLength < fieldLength) { StringBuffer paddedBuf = new StringBuffer(fieldLength); paddedBuf.append(stringVal); int difference = fieldLength - currentLength; paddedBuf.append(EMPTY_SPACE, 0, difference); stringVal = paddedBuf.toString(); } } } return stringVal; } }
//ResultSetInternalMethods
public interface ResultSetInternalMethods extends ResultSet { public abstract ResultSetInternalMethods copy() throws SQLException; public abstract boolean reallyResult(); public abstract Object getObjectStoredProc(int i, int j) throws SQLException; public abstract Object getObjectStoredProc(int i, Map map, int j) throws SQLException; public abstract Object getObjectStoredProc(String s, int i) throws SQLException; public abstract Object getObjectStoredProc(String s, Map map, int i) throws SQLException; public abstract String getServerInfo(); public abstract long getUpdateCount(); public abstract long getUpdateID(); public abstract void realClose(boolean flag) throws SQLException; public abstract void setFirstCharOfQuery(char c); public abstract void setOwningStatement(StatementImpl statementimpl); public abstract char getFirstCharOfQuery(); public abstract void clearNextResult(); public abstract ResultSetInternalMethods getNextResultSet(); public abstract void setStatementUsedForFetchingRows(PreparedStatement preparedstatement); public abstract void setWrapperStatement(Statement statement); public abstract void buildIndexMapping() throws SQLException; public abstract void initializeWithMetadata() throws SQLException; public abstract void redefineFieldsForDBMD(Field afield[]); public abstract void populateCachedMetaData(CachedResultSetMetaData cachedresultsetmetadata) throws SQLException; public abstract void initializeFromCachedMetaData(CachedResultSetMetaData cachedresultsetmetadata); }
发表评论
-
Mysql PreparedStatement 批处理
2016-12-06 18:09 1385JDBC驱动初始化-Mysql:http://donald-d ... -
MySQL ServerPreparedStatement查询
2016-12-06 14:42 1291JDBC驱动初始化-Mysql:http://donald-d ... -
Mysql预编译SQL
2016-12-05 19:06 1161JDBC驱动初始化-Mysql:http://donald-d ... -
ConnectionImp创建MysqlIO
2016-12-05 19:01 1021JDBC驱动初始化-Mysql:http://donald-d ... -
Mysql主从复制读写分离连接的获取
2016-12-01 08:43 1162JDBC驱动初始化-Mysql:http://donald-d ... -
Mysql负载均衡连接的获取
2016-12-01 08:38 1325Java动态代理:http://www.cnblogs.com ... -
JDBC连接的获取
2016-11-30 12:44 2933JDBC驱动初始化-Mysql:http://donald-d ... -
JDBC驱动初始化-Mysql
2016-11-30 12:41 3050JDBC驱动初始化-Mysql:http://donald-d ... -
mysql 存储过程
2016-07-17 14:49 899存储过程基础:http://sishuok.com/forum ... -
java.sql.Date,java.util.Date,java.sql.Timestamp的区别
2016-07-17 11:50 880java.sql.Date,jdbc映射数据库中的date类型 ... -
JDBC PreparedStatement 的用法
2016-07-15 17:27 893import java.sql.Connection; im ...
相关推荐
SQL(Structured Query Language)是用于管理关系数据库的标准语言,包括创建、更新、查询和管理数据。PHP提供了多种方法来执行SQL查询,例如使用mysqli或PDO(PHP Data Objects)扩展。 1. **mysqli扩展**:MySQL ...
MySQLSQL通用语句
MySQL SQL语法是数据库管理系统中用于操作数据的核心语言,它提供了创建、更新、查询和管理数据库的命令。在本文中,我们将深入探讨MySQL的一些主要语法结构。 1. **DDL(Data Definition Language)**:DDL用于...
java课设基于ssm人力人事管理系统源码+mysqlsql数据库脚本文件,该有的功能都有,适合java毕设课设,功能模块: 用户管理:包括登录、注册、用户信息修改等功能。 员工管理:实现员工的增加、删除、修改和查询等...
- **子查询**:在一个查询语句中嵌套另一个查询语句,通常用于更复杂的逻辑判断和数据筛选。 - **事务处理**:通过 `START TRANSACTION;`、`COMMIT;` 和 `ROLLBACK;` 等命令来确保一系列操作要么全部成功,要么全部...
- `IN` 子查询用于检查一个值是否在另一查询的结果集中,如:`WHERE column1 IN (SELECT column1 FROM table_name2 WHERE condition)` - `LIKE` 用于模式匹配,例如:`WHERE column1 LIKE 'x%'` 查找以 'x' 开头的...
数据分析师面试题SQL业务机器学习MySQLSQL优化技能和指导视频
MySQLSQL经典50题,R语言_tidyverse_解法_SQL50
MySQL索引优化是提高数据库性能和查询效率的关键步骤之一。索引是一种数据结构,用于快速查找数据库中的记录。合理设计和使用索引可以加快查询速度,并降低系统负载。下面将介绍MySQL索引优化的相关内容。 首先,...
资源名称:mysql sql语句大全资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
sql语句练习和疑问解析
1. **简化复杂查询**:将复杂的联接和子查询封装起来,使查询更简单。 2. **数据安全**:通过限制用户对底层表的直接访问,提供一定的数据隔离。 3. **逻辑分组**:创建符合特定业务需求的虚拟表。 4. **保护数据**...
MySQL的模糊查询是数据库操作中非常实用的功能,它允许用户使用特定的通配符来匹配不确定的数据。在SQL中,有四种主要的模糊查询模式,它们分别是百分号 `%`、下划线 `_`、方括号 `[ ]` 和 反斜杠 `[^ ]`。 1. 百分...
2、对查询进行优化,应尽量避免全表扫描,首先应考虑在where及orderby涉及的列上建立索引。 3、应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:...
MYSQL与SQL优化,自己编写MYSQL与SQL优化.ppt MYSQL与SQL优化.ppt
在数据库管理中,数据的组织方式对于数据查询和分析至关重要。MySQL 提供了两种转换数据布局的方法:行转列(Pivot)和列转行(Unpivot),这在处理复杂的数据汇总和展示时非常有用。本文将深入探讨这两种转换方法,...
本文将详细介绍如何通过SQL查询来实现这一功能,并对具体语句进行解析,帮助读者理解其中的工作原理及应用场景。 #### 1. 去除字段重复信息的背景与需求 在数据库应用中,为了确保数据的一致性和准确性,往往需要...
- 对复杂的查询进行分解,尝试将其拆分成多个简单查询。 - 使用EXPLAIN分析查询计划,找出性能瓶颈并针对性地进行优化。 **总结** MySQL性能优化涉及多个方面,包括合理配置关键参数、优化SQL语句等。通过对这些...
完成编码更改后,重新执行`EXPLAIN`和查询,结果显示查询计划已无问题,且重写的SQL语句中不再有`CONVERT`函数,这意味着可以充分利用索引,从而提高了查询速度。最终,查询执行时间降低到0.036秒,达到了预期的高效...