`
Donald_Draper
  • 浏览: 980070 次
社区版块
存档分类
最新评论

Mysql预编译SQL

    博客分类:
  • JDBC
阅读更多
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的预编译,从下面这一句开始:
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
分享到:
评论

相关推荐

    MySQL预编译功能

    MySQL 预编译功能是指在执行 SQL 语句之前,对 SQL 语句进行编译和优化,以提高执行效率。在 MySQL 中,预编译功能可以通过使用 Prepare 语句来实现。 预编译功能的优点是可以减少 SQL 语句的执行时间,因为在执行 ...

    MySQL 事务预编译查询和Perl DBI简化

    2. **预编译查询**:DBI提供了`prepare`方法来预编译SQL语句,然后用`execute`方法多次执行。这可以显著提高性能,尤其是在反复执行相同查询时: ```perl my $sth = $dbh-&gt;prepare('SELECT * FROM table WHERE id ...

    一文搞懂MySQL预编译

    MySQL预编译是一种提高数据库操作效率的技术,尤其在处理大量重复SQL语句时效果显著。预编译的主要目的是减少语法检查和编译的开销,从而提升数据库的性能。本文将深入探讨MySQL预编译的概念、好处、执行过程以及...

    MySQL预编译功能详解

    MySQL的预编译功能是一种优化技术,主要用于提高数据库操作的性能,特别是在执行大量重复的SQL语句时。预编译的核心思想是将SQL语句的语法检查和编译过程提前到第一次执行时完成,之后只需替换不同的参数即可,避免...

    mysql frm转sql

    MySqlFrm.exe是c#版本的frm转sql工具,需要.net 4.0与mysql环境,CMD命令行如下: mysqlfrm &lt;username&gt; &lt;password&gt; &lt;port&gt; 例如: mysqlfrm root pass 3306 c:\dbcopy 会将c:\dbcopy目录下所有的frm转换为...

    mysql源码编译工具

    安装这个工具后,你可以通过解析MySQL的Yacc(YACC:Yet Another Compiler-Compiler)文件来生成C代码,这些代码是MySQL解析SQL语句所必需的。 接下来,我们提到的是`Perl`,在这里具体为`ActivePerl-5.16.3.1604-...

    mysql自动编译安装

    MySQL是一种广泛使用的开源关系型数据库管理系统(RDBMS),它基于结构化查询语言(SQL)。在Linux环境下,如果你想要从源代码进行编译安装MySQL,这通常是为了获得更高的定制性或者适应特定系统环境。以下是对...

    Qt编译MySQL驱动

    在本文中,我们将深入探讨如何在Qt环境中编译MySQL驱动,以便在Qt应用程序中与MySQL数据库进行交互。首先,我们要明确的是,这个过程通常适用于Qt 5.2及其更高版本,因为这是支持编译MySQL驱动的最低要求。在这个...

    qt-mysql驱动编译教程及驱动

    在本文中,我们将深入探讨如何在Qt环境中编译MySQL驱动,以便在Qt应用程序中与MySQL数据库进行交互。这个过程可能对新手来说有些复杂,因为网上的教程可能存在误导或不完整的情况。但不用担心,我们将逐步解释整个...

    linux下PC机和ARM开发板的QT下mysql驱动编译使用

    这里使用了`-qt-sql-mysql`选项来静态编译MySQL驱动。 3. 执行`make`和`make install`,这将生成包含MySQL驱动的QT库文件。 接下来是ARM开发板的QT MySQL驱动编译: 1. 对于嵌入式版本,因为需要交叉编译,所以...

    sql和mysql jdbc包

    在上述示例中,`PreparedStatement`预编译了SQL语句,提高了执行效率并降低了SQL注入的风险。`ResultSet`对象则用于存储查询结果,通过遍历结果集来获取数据。 总结来说,SQL2005和MySQL是两种不同的数据库系统,...

    erlang_mysql编译好了

    这里提到的“erlang_mysql编译好了”可能是指已经成功编译了这样的库,它提供了一个Erlang应用程序,使得Erlang进程可以直接与MySQL服务器通信。这个过程通常涉及以下步骤: 1. **获取源代码**:你需要找到Erlang ...

    SQL.rar_labview mysql_mysql labview_sql

    标题“SQL.rar_labview mysql_mysql labview_sql”和描述“在labview中实现数据库MySQL调用的节点函数...在实际项目中,确保遵循最佳实践,如使用预编译的SQL语句防止SQL注入,以及适时关闭数据库连接以优化资源利用。

    mysql.rar_MYSQL数据库_MySQL软件_SQL软件

    - 存储过程(Stored Procedure):预编译的SQL语句集合,可以提高性能并简化复杂操作。 - 触发器(Trigger):自动执行的数据库操作,基于特定的事件(如INSERT、UPDATE或DELETE)。 通过“www.pudn.com.txt”文件...

    基于MySQL的SQL注入攻击

    1. **使用预编译语句和参数化查询**:预编译语句可以防止SQL注入,因为它们将SQL语句和数据分开处理,避免了恶意代码的执行。 2. **输入验证和数据清理**:对所有用户输入进行验证,确保只接受预期格式的数据,并对...

    MySQL开发者SQL权威指南_MYSQL_

    7. **存储过程与函数**: 存储过程是一组预编译的SQL语句,可提高代码复用性和执行效率。函数则是在查询中可以直接调用的预定义操作,如内置数学函数、字符串函数和日期时间函数。 8. **触发器**: 触发器是响应特定...

    mysql5.7.23源码编译包带boost

    8. **SQL标准的兼容性**:MySQL 5.7在遵循SQL标准方面取得了显著进步,例如支持窗口函数和 Common Table Expressions(CTE),使SQL语句编写更为简洁和强大。 综上所述,MySQL 5.7.23 源码编译包带Boost是一个全面...

    java+mysql 机票预订系统 项目实战

    为了优化性能,可能还应用了预编译的PreparedStatement,以防止SQL注入攻击。 此外,项目可能还包括异常处理、日志记录、安全性考虑等多方面的实践。例如,对敏感信息如密码进行加密存储,使用HTTPS协议确保通信...

Global site tag (gtag.js) - Google Analytics