mysql预编译表名_Mysql预编译SQL

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的预编译,从下面这一句开始:

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());

}

}

}

0

0

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2016-12-05 19:06

浏览 796

分类:数据库

评论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值