提高MySQL数据库查询效率的几个技巧[php程序员必看]

 更新时间:2016年11月25日 16:32  点击:2110

MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我在开发一个P2P应用的时候曾经使用MySQL来保存P2P节点,由于P2P的应用中,结点数动辄上万个,而且节点变化频繁,因此一定要保持查询和插入的高效.以下是我在使用过程中做的提高效率的三个有效的尝试.

l
使用statement进行绑定查询
使用statement可以提前构建查询语法树,在查询时不再需要构建语法树就直接查询.因此可以很好的提高查询的效率. 这个方法适合于查询条件固定但查询非常频繁的场合.
使用方法是:

绑定, 创建一个MYSQL_STMT变量,与对应的查询字符串绑定,字符串中的问号代表要传入的变量,每个问号都必须指定一个变量.
查询, 输入每个指定的变量, 传入MYSQL_STMT变量用可用的连接句柄执行.
代码如下:

//1.绑定
bool CDBManager::BindInsertStmt(MYSQL * connecthandle)
{
       //作插入操作的绑定
       MYSQL_BIND insertbind[FEILD_NUM];
       if(m_stInsertParam == NULL)
              m_stInsertParam = new CHostCacheTable;
       m_stInsertStmt = mysql_stmt_init(connecthandle);
       //构建绑定字符串
       char insertSQL[SQL_LENGTH];
       strcpy(insertSQL, "insert into HostCache(SessionID, ChannelID, ISPType, "
              "ExternalIP, ExternalPort, InternalIP, InternalPort) "
              "values(?, ?, ?, ?, ?, ?, ?)");
       mysql_stmt_prepare(m_stInsertStmt, insertSQL, strlen(insertSQL));
       int param_count= mysql_stmt_param_count(m_stInsertStmt);
       if(param_count != FEILD_NUM)
              return false;
       //填充bind结构数组, m_sInsertParam是这个statement关联的结构变量
       memset(insertbind, 0, sizeof(insertbind));
       insertbind[0].buffer_type = MYSQL_TYPE_STRING;
       insertbind[0].buffer_length = ID_LENGTH /* -1 */;
       insertbind[0].buffer = (char *)m_stInsertParam->sessionid;
       insertbind[0].is_null = 0;
       insertbind[0].length = 0;

       insertbind[1].buffer_type = MYSQL_TYPE_STRING;
       insertbind[1].buffer_length = ID_LENGTH /* -1 */;
       insertbind[1].buffer = (char *)m_stInsertParam->channelid;
       insertbind[1].is_null = 0;
       insertbind[1].length = 0;

       insertbind[2].buffer_type = MYSQL_TYPE_TINY;
       insertbind[2].buffer = (char *)&m_stInsertParam->ISPtype;
       insertbind[2].is_null = 0;
       insertbind[2].length = 0;

       insertbind[3].buffer_type = MYSQL_TYPE_LONG;
       insertbind[3].buffer = (char *)&m_stInsertParam->externalIP;
       insertbind[3].is_null = 0;
       insertbind[3].length = 0;


       insertbind[4].buffer_type = MYSQL_TYPE_SHORT;
       insertbind[4].buffer = (char *)&m_stInsertParam->externalPort;
       insertbind[4].is_null = 0;
       insertbind[4].length = 0;

       insertbind[5].buffer_type = MYSQL_TYPE_LONG;
       insertbind[5].buffer = (char *)&m_stInsertParam->internalIP;
       insertbind[5].is_null = 0;
       insertbind[5].length = 0;

       insertbind[6].buffer_type = MYSQL_TYPE_SHORT;
       insertbind[6].buffer = (char *)&m_stInsertParam->internalPort;
       insertbind[6].is_null = 0;
       insertbind[6].is_null = 0;
       //绑定
       if (mysql_stmt_bind_param(m_stInsertStmt, insertbind))
              return false;
       return true;
}

//2.查询
bool CDBManager::InsertHostCache2(MYSQL * connecthandle, char * sessionid, char * channelid, int ISPtype, \
              unsigned int eIP, unsigned short eport, unsigned int iIP, unsigned short iport)
{
       //填充结构变量m_sInsertParam
       strcpy(m_stInsertParam->sessionid, sessionid);
       strcpy(m_stInsertParam->channelid, channelid);
       m_stInsertParam->ISPtype = ISPtype;
       m_stInsertParam->externalIP = eIP;
       m_stInsertParam->externalPort = eport;
       m_stInsertParam->internalIP = iIP;
       m_stInsertParam->internalPort = iport;
       //执行statement,性能瓶颈处
       if(mysql_stmt_execute(m_stInsertStmt))
              return false;
       return true;
}

l
随机的获取记录
在某些数据库的应用中, 我们并不是要获取所有的满足条件的记录,而只是要随机挑选出满足条件的记录. 这种情况常见于数据业务的统计分析,从大容量数据库中获取小量的数据的场合.

有两种方法可以做到
1.       常规方法,首先查询出所有满足条件的记录,然后随机的挑选出部分记录.这种方法在满足条件的记录数很多时效果不理想.
2.       使用limit语法,先获取满足条件的记录条数, 然后在sql查询语句中加入limit来限制只查询满足要求的一段记录. 这种方法虽然要查询两次,但是在数据量大时反而比较高效.
示例代码如下:

//1.常规的方法
//性能瓶颈,10万条记录时,执行查询140ms, 获取结果集500ms,其余可忽略
int CDBManager::QueryHostCache(MYSQL* connecthandle, char * channelid, int ISPtype, CDBManager::CHostCacheTable * &hostcache)
{

       char selectSQL[SQL_LENGTH];
       memset(selectSQL, 0, sizeof(selectSQL));
       sprintf(selectSQL,"select * from HostCache where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
       if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
              return 0;
       //获取结果集
       m_pResultSet = mysql_store_result(connecthandle);
       if(!m_pResultSet)   //获取结果集出错
              return 0;
       int iAllNumRows = (int)(mysql_num_rows(m_pResultSet));      ///<所有的搜索结果数
       //计算待返回的结果数
       int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)? iAllNumRows:RETURN_QUERY_HOST_NUM;
       if(iReturnNumRows <= RETURN_QUERY_HOST_NUM)
       {
              //获取逐条记录
              for(int i = 0; i<iReturnNumRows; i++)
              {
                     //获取逐个字段
                     m_Row = mysql_fetch_row(m_pResultSet);
                     if(m_Row[0] != NULL)
                            strcpy(hostcache.sessionid, m_Row[0]);
                     if(m_Row[1] != NULL)
                            strcpy(hostcache.channelid, m_Row[1]);
                     if(m_Row[2] != NULL)
                            hostcache.ISPtype      = atoi(m_Row[2]);
                     if(m_Row[3] != NULL)
                            hostcache.externalIP   = atoi(m_Row[3]);
                     if(m_Row[4] != NULL)
                            hostcache.externalPort = atoi(m_Row[4]);
                     if(m_Row[5] != NULL)
                            hostcache.internalIP   = atoi(m_Row[5]);
                     if(m_Row[6] != NULL)
                            hostcache.internalPort = atoi(m_Row[6]);             
              }
       }
       else
       {
              //随机的挑选指定条记录返回
              int iRemainder = iAllNumRows%iReturnNumRows;    ///<余数
              int iQuotient = iAllNumRows/iReturnNumRows;      ///<商
              int iStartIndex = rand()%(iRemainder + 1);         ///<开始下标

              //获取逐条记录
        for(int iSelectedIndex = 0; iSelectedIndex < iReturnNumRows; iSelectedIndex++)
        {
                            mysql_data_seek(m_pResultSet, iStartIndex + iQuotient * iSelectedIndex);
                            m_Row = mysql_fetch_row(m_pResultSet);
                  if(m_Row[0] != NULL)
                       strcpy(hostcache[iSelectedIndex].sessionid, m_Row[0]);
                   if(m_Row[1] != NULL)
                                   strcpy(hostcache[iSelectedIndex].channelid, m_Row[1]);
                   if(m_Row[2] != NULL)
                       hostcache[iSelectedIndex].ISPtype      = atoi(m_Row[2]);
                   if(m_Row[3] != NULL)
                       hostcache[iSelectedIndex].externalIP   = atoi(m_Row[3]);
                    if(m_Row[4] != NULL)
                       hostcache[iSelectedIndex].externalPort = atoi(m_Row[4]);
                   if(m_Row[5] != NULL)
                       hostcache[iSelectedIndex].internalIP   = atoi(m_Row[5]);
                   if(m_Row[6] != NULL)
                       hostcache[iSelectedIndex].internalPort = atoi(m_Row[6]);
        }
      }
       //释放结果集内容
       mysql_free_result(m_pResultSet);
       return iReturnNumRows;
}

//2.使用limit版
int CDBManager::QueryHostCache(MYSQL * connecthandle, char * channelid, unsigned int myexternalip, int ISPtype, CHostCacheTable * hostcache)
{
       //首先获取满足结果的记录条数,再使用limit随机选择指定条记录返回
       MYSQL_ROW row;
       MYSQL_RES * pResultSet;
       char selectSQL[SQL_LENGTH];
       memset(selectSQL, 0, sizeof(selectSQL));

       sprintf(selectSQL,"select count(*) from HostCache where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
       if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
              return 0;
       pResultSet = mysql_store_result(connecthandle);
       if(!pResultSet)      
              return 0;
       row = mysql_fetch_row(pResultSet);
       int iAllNumRows = atoi(row[0]);
       mysql_free_result(pResultSet);
       //计算待取记录的上下范围
       int iLimitLower = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
              0:(rand()%(iAllNumRows - RETURN_QUERY_HOST_NUM));
       int iLimitUpper = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
              iAllNumRows:(iLimitLower + RETURN_QUERY_HOST_NUM);
       //计算待返回的结果数
       int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
               iAllNumRows:RETURN_QUERY_HOST_NUM;


       //使用limit作查询
       sprintf(selectSQL,"select SessionID, ExternalIP, ExternalPort, InternalIP, InternalPort "
              "from HostCache where ChannelID = '%s' and ISPtype = %d limit %d, %d"
              , channelid, ISPtype, iLimitLower, iLimitUpper);
       if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
              return 0;
       pResultSet = mysql_store_result(connecthandle);
       if(!pResultSet)
              return 0;
       //获取逐条记录
       for(int i = 0; i<iReturnNumRows; i++)
       {
              //获取逐个字段
              row = mysql_fetch_row(pResultSet);
              if(row[0] != NULL)
                     strcpy(hostcache.sessionid, row[0]);
              if(row[1] != NULL)
                     hostcache.externalIP   = atoi(row[1]);
              if(row[2] != NULL)
                     hostcache.externalPort = atoi(row[2]);
              if(row[3] != NULL)
                     hostcache.internalIP   = atoi(row[3]);
              if(row[4] != NULL)
                     hostcache.internalPort = atoi(row[4]);            
       }
       //释放结果集内容
       mysql_free_result(pResultSet);
       return iReturnNumRows;
}

l
使用连接池管理连接.
在有大量节点访问的数据库设计中,经常要使用到连接池来管理所有的连接.
一般方法是:建立两个连接句柄队列,空闲的等待使用的队列和正在使用的队列.
当要查询时先从空闲队列中获取一个句柄,插入到正在使用的队列,再用这个句柄做数据库操作,完毕后一定要从使用队列中删除,再插入到空闲队列.
设计代码如下:

//定义句柄队列
typedef std::list<MYSQL *> CONNECTION_HANDLE_LIST;
typedef std::list<MYSQL *>::iterator CONNECTION_HANDLE_LIST_IT;

//连接数据库的参数结构
class CDBParameter

{
public:
       char *host;                                 ///<主机名
       char *user;                                 ///<用户名
       char *password;                         ///<密码
       char *database;                           ///<数据库名
       unsigned int port;                 ///<端口,一般为0
       const char *unix_socket;      ///<套接字,一般为NULL
       unsigned int client_flag; ///<一般为0
};

//创建两个队列
CONNECTION_HANDLE_LIST m_lsBusyList;                ///<正在使用的连接句柄
CONNECTION_HANDLE_LIST m_lsIdleList;                  ///<未使用的连接句柄

//所有的连接句柄先连上数据库,加入到空闲队列中,等待使用.
bool CDBManager::Connect(char * host /* = "localhost" */, char * user /* = "chenmin" */, \
                                           char * password /* = "chenmin" */, char * database /* = "HostCache" */)
{
       CDBParameter * lpDBParam = new CDBParameter();
       lpDBParam->host = host;
       lpDBParam->user = user;
       lpDBParam->password = password;
       lpDBParam->database = database;
       lpDBParam->port = 0;
       lpDBParam->unix_socket = NULL;
       lpDBParam->client_flag = 0;
       try
       {
              //连接
              for(int index = 0; index < CONNECTION_NUM; index++)
              {
                     MYSQL * pConnectHandle = mysql_init((MYSQL*) 0);     //初始化连接句柄
                     if(!mysql_real_connect(pConnectHandle, lpDBParam->host, lpDBParam->user, lpDBParam->password,\
       lpDBParam->database,lpDBParam->port,lpDBParam->unix_socket,lpDBParam->client_fla))
                            return false;
//加入到空闲队列中
                     m_lsIdleList.push_back(pConnectHandle);
              }
       }
       catch(...)
       {
              return false;
       }
       return true;
}

//提取一个空闲句柄供使用
MYSQL * CDBManager::GetIdleConnectHandle()
{
       MYSQL * pConnectHandle = NULL;
       m_ListMutex.acquire();
       if(m_lsIdleList.size())
       {
              pConnectHandle = m_lsIdleList.front();      
              m_lsIdleList.pop_front();
              m_lsBusyList.push_back(pConnectHandle);
       }
       else //特殊情况,闲队列中为空,返回为空
       {
              pConnectHandle = 0;
       }
       m_ListMutex.release();

       return pConnectHandle;
}

//从使用队列中释放一个使用完毕的句柄,插入到空闲队列
void CDBManager::SetIdleConnectHandle(MYSQL * connecthandle)
{
       m_ListMutex.acquire();
       m_lsBusyList.remove(connecthandle);
       m_lsIdleList.push_back(connecthandle);
       m_ListMutex.release();
}
//使用示例,首先获取空闲句柄,利用这个句柄做真正的操作,然后再插回到空闲队列
bool CDBManager::DeleteHostCacheBySessionID(char * sessionid)
{
       MYSQL * pConnectHandle = GetIdleConnectHandle();
       if(!pConnectHandle)
              return 0;
       bool bRet = DeleteHostCacheBySessionID(pConnectHandle, sessionid);
       SetIdleConnectHandle(pConnectHandle);
       return bRet;
}
//传入空闲的句柄,做真正的删除操作
bool CDBManager::DeleteHostCacheBySessionID(MYSQL * connecthandle, char * sessionid)
{
       char deleteSQL[SQL_LENGTH];
       memset(deleteSQL, 0, sizeof(deleteSQL));
       sprintf(deleteSQL,"delete from HostCache where SessionID = '%s'", sessionid);
       if(mysql_query(connecthandle,deleteSQL) != 0) //删除
              return false;
       return true;
}

 

Google 个性化主页类似,如何保存最后的布局一

<style type="text/css">
*{
        padding:0;margin:0
}

.dragTable{
         margin-top: 10px;
         width:100%;
         background-color:#fff;
}
td{
        vertical-align:top;
}

.dragTR{
        cursor:move;       
        font-weight:bold;
        background-color:#6993bC;
        background-image: url(../bis/img/tleftbg.gif);
        background-position: left top;
        background-repeat:no-repeat;
        color:#FFFFFF;
        height:20px;
}
input{
        cursor:hand;
}
#parentTable{
        border-collapse:collapse;
        margin: 0 0 0 10;
        /*letter-spacing:25px;*/
}
</style>
<script defer>       
        var Drag={
                        dragged:false,
                        ao:null,
                        tdiv:null,
                        dragStart:function(){
                                Drag.ao=event.srcElement;
                                if((Drag.ao.tagName=="TD")||(Drag.ao.tagName=="TR")){
                                        Drag.ao=Drag.ao.offsetParent;
                                        Drag.ao.style.zIndex=100;
                                }else{
                                        return;
                                }
                                Drag.dragged=true;
                                Drag.tdiv=document.createElement("div");
                                Drag.tdiv.innerHTML=Drag.ao.outerHTML;
                                Drag.ao.style.border="1px dashed red";
                                Drag.tdiv.style.display="block";
                                Drag.tdiv.style.position="absolute";
                                Drag.tdiv.style.filter="alpha(opacity=70)";
                                Drag.tdiv.style.cursor="move";
                                Drag.tdiv.style.border="1px solid #000000";
                                Drag.tdiv.style.width=Drag.ao.offsetWidth;
                                Drag.tdiv.style.height=Drag.ao.offsetHeight;
                                Drag.tdiv.style.top=Drag.getInfo(Drag.ao).top;
                                Drag.tdiv.style.left=Drag.getInfo(Drag.ao).left;
                                document.body.appendChild(Drag.tdiv);
                                Drag.lastX=event.clientX;
                                Drag.lastY=event.clientY;
                                Drag.lastLeft=Drag.tdiv.style.left;
                                Drag.lastTop=Drag.tdiv.style.top;
                        },
                        draging:function(){//重要:判断MOUSE的位置

                                if(!Drag.dragged||Drag.ao==null) return;
                                var tX=event.clientX;
                                var tY=event.clientY;
                                Drag.tdiv.style.left=parseInt(Drag.lastLeft)+tX-Drag.lastX;
                                Drag.tdiv.style.top=parseInt(Drag.lastTop)+tY-Drag.lastY;
                                for(var i=0;i<parentTable.cells.length;i++){
                                        var parentCell=Drag.getInfo(parentTable.cells[i]);
                                        if(tX>=parentCell.left&&tX<=parentCell.right&&tY>=parentCell.top&&tY<=parentCell.bottom){
                                                var subTables=parentTable.cells[i].getElementsByTagName("table");
                                                if(subTables.length==0){
                                                        if(tX>=parentCell.left&&tX<=parentCell.right&&tY>=parentCell.top&&tY<=parentCell.bottom){
                                                                parentTable.cells[i].appendChild(Drag.ao);
                                                        }
                                                        break;
                                                }
                                                for(var j=0; j<subTables.length; j++){
                                                        var subTable=Drag.getInfo(subTables[j]);
                                                        if(tX>=subTable.left&&tX<=subTable.right&&tY>=subTable.top&&tY<=subTable.bottom){
                                                                parentTable.cells[i].insertBefore(Drag.ao,subTables[j]);
                                                                break;
                                                        }else{
                                                                parentTable.cells[i].appendChild(Drag.ao);
                                                        }
                                           }
                                        }
                                }
                        },
                        dragEnd:function(){
                                if(!Drag.dragged)        return;
                                Drag.dragged=false;
                                Drag.mm=Drag.repos(150,15);
                                Drag.ao.style.borderWidth="0px";
                                //Drag.ao.style.borderTop="1px solid #3366cc";
                                Drag.tdiv.style.borderWidth="0px";
                                Drag.ao.style.zIndex=1;
                                setCookie(Drag.ao.id+"top",Drag.getInfo(Drag.ao).top);
                                setCookie(Drag.ao.id+"left",Drag.getInfo(Drag.ao).left);
                                displaySaveLayout();
                        },
                        getInfo:function(o){//取得坐标
                                var to=new Object();
                                to.left=to.right=to.top=to.bottom=0;
                                var twidth=o.offsetWidth;
                                var theight=o.offsetHeight;
                                while(o!=document.body){
                                        to.left+=o.offsetLeft;
                                        to.top+=o.offsetTop;
                                        o=o.offsetParent;
                                }
                                to.right=to.left+twidth;
                                to.bottom=to.top+theight;
                                return to;
                        },
                        repos:function(aa,ab){
                                var f=Drag.tdiv.filters.alpha.opacity;
                                var tl=parseInt(Drag.getInfo(Drag.tdiv).left);
                                var tt=parseInt(Drag.getInfo(Drag.tdiv).top);
                                var kl=(tl-Drag.getInfo(Drag.ao).left)/ab;
                                var kt=(tt-Drag.getInfo(Drag.ao).top)/ab;
                                var kf=f/ab;
                                return setInterval(
                                        function(){
                                                if(ab<1){
                                                        clearInterval(Drag.mm);
                                                        Drag.tdiv.removeNode(true);
                                                        Drag.ao=null;
                                                        return;
                                                }
                                                ab--;
                                                tl-=kl;
                                                tt-=kt;
                                                f-=kf;
                                                Drag.tdiv.style.left=parseInt(tl)+"px";
                                                Drag.tdiv.style.top=parseInt(tt)+"px";
                                                Drag.tdiv.filters.alpha.opacity=f;
                                        }
                                        ,aa/ab)
                        },

                        inint:function(){//初始化

                                for(var i=0;i<parentTable.cells.length;i++){
                                        var subTables=parentTable.cells[i].getElementsByTagName("table");
                                        for(var j=0;j<subTables.length;j++){
                                                if(subTables[j].className!="dragTable") break;
                                                //subTables[j].style.position = "absolute";
                                                //subTables[j].style.left = getCookie(subTables[j].id+"left");
                                                //subTables[j].style.top = getCookie(subTables[j].id+"top");
                                                //subTables[j].style.position = "relative";
                                                subTables[j].rows[0].className="dragTR";
                                                subTables[j].rows[0].attachEvent("onmousedown",Drag.dragStart);
                                        }
                                }
                                document.onmousemove=Drag.draging;
                                document.onmouseup=Drag.dragEnd;
                        }
                }//end of Object Drag

                Drag.inint();
                /*
                function _show(str){
                        var w=window.open('','');
                        var d=w.document;
                        d.open();
                        str=str.replace(/=(?!")(.*?)(?!")( |>)/g,"=\"$1\"$2");
                        str=str.replace(/(<)(.*?)(>)/g,"<span style='color:red;'>&lt;$2&gt;</span><br />");
                        str=str.replace(/\r/g,"<br />\n");
                        d.write(str);
                }
                */
                function collapseExpand()
                {
                        var imgObj = event.srcElement;
                        var contab = imgObj.parentElement.parentElement.parentElement.parentElement;

                        if (imgObj.type == "image" && contab.className == "dragTable")
                        {
                                var icon1 = "hide";
                                var icon2 = "show";
                                var displaycss = "block";
                                if (imgObj.src.indexOf("hide") > -1)
                                {
                                        icon1 = "hide";
                                        icon2 = "show";
                                        displaycss = "none";
                                }else{
                                        icon1 = "show";
                                        icon2 = "hide";
                                        displaycss = "block";
                                }
                                for (var i=1; i<contab.rows.length; i++ )
                                {
                                        contab.rows(i).style.display = displaycss;
                                }
                                imgObj.src = imgObj.src.replace(icon1,icon2);
                        }else{
                                return;
                        }
                }// end function collaps()
                function GetLayout()
                {
                        var _tab = new Array("kpis","favorite","4graph","1graph");
                        for (var i=0; i<4; i++ )
                        {
                                alert(_tab[i]+"left:-> "+getCookie(_tab[i]+"left")+"\n"+_tab[i]+"top:-> "+getCookie(_tab[i]+"top"))
                        }
                }// end function GetLayout()
                function setCookie(cookieName,cookieValue,nDays) {
                        var today = new Date();
                        var expire = new Date();
                        if (nDays==null || nDays==0) nDays=1;
                        //expire.setTime(today.getTime() + 3600000*24*nDays);
                        expire.setTime(today.getTime());
                        document.cookie = cookieName+"="+escape(cookieValue);//+ ";expires="+expire.toGMTString();
                        //document.cookie = cookieName+"="+escape(cookieValue)+ ";expires="+expire.toGMTString();
                }
                function displaySaveLayout()
                {
                        var sl = document.getElementById("savelayout");
                        if (sl.style.display == "none")
                        {
                                sl.style.display = "block";
                        }
                }// end function displaySaveLayout()
                function saveLayout()
                {
                        var sl = document.getElementById("savelayout");
                        if (sl.style.display == "block")
                        {
                                sl.style.display = "none";
                                //sl.innerText = "页面布局保存成功.";
                                window.status = "页面布局保存成功.";
                        }
                        var tables = document.getElementsByTagName("table");
                        for (var i=0; tables.length; i++)
                        {
                                try
                                {
                                        if (tables[i].id != "parentTable" && typeof(tables[i].id) != "undefined" && tables[i].id )
                                        {
                                                //alert(tables[i].id+":\nleft->"+getCookie(tables[i].id+"left")+"\t\t top:"+getCookie(tables[i].id+"top"));
                                                alert(tables[i].id+" left:"+tables[i].style.pixLeft );
                                               
                                        }//
                                }catch(e)
                                {
                                        return;
                                }
                        }// end for loop
                }// end function saveLayout()
</script>

Apache和PHP网页的编码问题分析

谈谈Apache和PHP网页的编码。还有一篇关于MySQL字符集的:http://potatows.eeie.cn/?p=39
谈到Apache的编码我们就要涉及到3个东西

http标记语言中的<META http-equiv="content-type" content="text/html; charset=xxx">标签
PHP中的header("content-type:text/html; charset=xxx");函数
Apache配置文件httpd.conf中的AddDefaultCharset
一、<META http-equiv="content-type" content="text/html; charset=xxx">标签
按顺序来,先说这个<META>标签,这个标签有很多功能的,具体请点这里。
我今天想说只是上面提到的那种形式。解释一下<META http-equiv="content-type" content="text/html; charset=utf-8">,意思是对这个网页进行声明,让浏览器对整个页面的内容采用xxx编码,xxx可以为GB2312,GBK,UTF-8(和MySQL不同,MySQL是UTF8)等等。因此,大部分页面可以采用这种方式来告诉浏览器显示这个页面的时候采用什么编码,这样才不会造成编码错误而产生乱码。但是有的时候我们会发现有了这句还是不行,不管xxx是哪一种,浏览器采用的始终都是一种编码,这个情况我后面会谈到。
请注意,<meta>是属于html信息的,仅仅是一个声明,它起作用表明服务器已经把HTML信息传到了浏览器。

二、header("content-type:text/html; charset=xxx");
这个函数header()的作用是把括号里面的信息发到http标头。关于此函数具体用法请点击这里。
如果括号里面的内容为文中所说那样,那作用和<META>标签基本相同,大家对照第一个看发现字符都差不多的。但是不同的是如果有这段函数,浏览器就会永远采用你所要求的xxx编码,绝对不会不听话,因此这个函数是很有用的。为什么会这样呢?那就得说说HTTPS标头和HTML信息的差别了:
引用:
https标头是服务器以HTTP协议传送HTML信息到浏览器前所送出的字串。
因为meta标签是属于html信息的,所以header()发送的内容先到达浏览器,通俗点就是header()的优先级高于meta(不知道可不可以这样讲)。加入一个php页面既有header("content-type:text/html; charset=xxx"),又有<META http-equiv="content-type" content="text/html; charset=xxx">,浏览器就只认前者http标头而不认meta了。当然这个函数只能在php页面内使用。
同样也留有一个问题,为什么前者就绝对起作用,而后者有时候就不行呢?这就是接下来要谈的Apache的原因了。

三、AddDefaultCharset
Apache根目录的conf文件夹里,有整个Apache的配置文档httpd.conf。具体如何配置apache请点击这里([url=thread-2674-1-1.html]windows[/url],[url=thread-1381-1-1.html]linux[/url])。
用文本编辑器打开httpd.conf,第708行(不同版本可能不同)有AddDefaultCharset xxx,xxx为编码名称。这行代码的意思:设置整个服务器内的网页文件https标头里的字符集为你默认的xxx字符集。有这行,就相当于给每个文件都加了一行header("content-type:text/html; charset=xxx")。这下就明白为什么明明meta设置了是utf-8,可浏览器始终采用gb2312的原因。
如果网页里有header("content-type:text/html; charset=xxx"),就把默认的字符集改为你设置的字符集,所以这个函数永远有用。如果把AddDefaultCharset xxx前面加个“#”,注释掉这句,而且页面里不含header("content-type…"),那这个时候就轮到meta标签起作用了。


总结:
来个排序

header("content-type:text/html; charset=xxx")
AddDefaultCharset xxx
<META http-equiv="content-type" content="text/html; charset=xxx">
如果你是web程序员,给你的每个页面都加个header("content-type:text/html; charset=xxx"),保证它在任何服务器都能正确显示,可移植性强。
至于那句AddDefaultCharset xxx,要不要注释就仁者见仁了。反正我是注释掉了,不过我写页子也要写header(),便于放到不同的服务器上能正常显示。

增加中文水印
<?php
/*-------------------------------------------------------------
**描述:这是用于给指定图片加底部水印(不占用图片显示区域)的自定义类,需创建对象调用
**版本:v1.0
**创建:2007-10-09
**更新:2007-10-09
**人员:老肥牛([email]fatkenme@163.com[/email]  QQ:70177108)
**说明:1、需要gd库支持,需要iconv支持(php5已经包含不用加载)
        2、只适合三种类型的图片,jpg/jpeg/gif/png,其它类型不处理
        3、注意图片所在目录的属性必须可写
        4、调用范例:
            $objImg = new MyWaterDownChinese();
            $objImg->Path = "images/";
            $objImg->FileName = "1.jpg";
            $objImg->Text = "胖胖交友网 [url]www.ppfriend.com[/url]";
            $objImg->Font = "./font/simhei.ttf";
            $objImg->Run();
**成员函数:
----------------------------------------------------------------*/
class MyWaterDownChinese{
          var $Path = "./";  //图片所在目录相对于调用此类的页面的相对路径
          var $FileName = ""; //图片的名字,如“1.jpg”
          var $Text = "";   //图片要加上的水印文字,支持中文
          var $TextColor = "#ffffff"; //文字的颜色,gif图片时,字体颜色只能为黑色
          var $TextBgColor = "#000000"; //文字的背景条的颜色
          var $Font = "c://windows//fonts//simhei.ttf"; //字体的存放目录,相对路径
          var $OverFlag = true; //是否要覆盖原图,默认为覆盖,不覆盖时,自动在原图文件名后+"_water_down",如“1.jpg”=> "1_water_down.jpg"
          var $BaseWidth = 200; //图片的宽度至少要>=200,才会加上水印文字。
        
//------------------------------------------------------------------
//功能:类的构造函数(php5.0以上的形式)
//参数:无
//返回:无
function __construct(){;}

//------------------------------------------------------------------
//功能:类的析构函数(php5.0以上的形式)
//参数:无
//返回:无
function __destruct(){;}
//------------------------------------------------------------------

//------------------------------------
//功能:对象运行函数,给图片加上水印
//参数:无
//返回:无
function Run()
{
    if($this->FileName == "" || $this->Text == "")
        return;
    //检测是否安装GD库
    if(false == function_exists("gd_info"))
    {
        echo "系统没有安装GD库,不能给图片加水印.";
        return;
    }
    //设置输入、输出图片路径名
    $arr_in_name = explode(".",$this->FileName);
    //
    $inImg = $this->Path.$this->FileName;
    $outImg = $inImg;
    $tmpImg = $this->Path.$arr_in_name[0]."_tmp.".$arr_in_name[1]; //临时处理的图片,很重要
    if(!$this->OverFlag)
        $outImg = $this->Path.$arr_in_name[0]."_water_down.".$arr_in_name[1];
    //检测图片是否存在
    if(!file_exists($inImg))
        return ;
    //获得图片的属性
    $groundImageType = @getimagesize($inImg);
    $imgWidth = $groundImageType[0];
    $imgHeight = $groundImageType[1];
    $imgType = $groundImageType[2];
    if($imgWidth < $this->BaseWidth)  //小于基本宽度,不处理
        return;
   
    //图片不是jpg/jpeg/gif/png时,不处理
    switch($imgType)
    {
         case 1:
              $image = imagecreatefromgif($inImg);
              $this->TextBgColor = "#ffffff"; //gif图片字体只能为黑,所以背景颜色就设置为白色
              break; 
         case 2:
              $image = imagecreatefromjpeg($inImg);
              break; 
         case 3:
              $image = imagecreatefrompng($inImg);
              break; 
         default:
              return;
              break;
    }
    //创建颜色
    $color = @imagecolorallocate($image,hexdec(substr($this->TextColor,1,2)),hexdec(substr($this->TextColor,3,2)),hexdec(substr($this->TextColor,5,2))); //文字颜色
    //生成一个空的图片,它的高度在底部增加水印高度
    $newHeight = $imgHeight+20;
    $objTmpImg = @imagecreatetruecolor($imgWidth,$newHeight);
    $colorBg = @imagecolorallocate($objTmpImg,hexdec(substr($this->TextBgColor,1,2)),hexdec(substr($this->TextBgColor,3,2)),hexdec(substr($this->TextBgColor,5,2))); //背景颜色   
    //填充图片的背景颜色
    @imagefill ($objTmpImg,0,0,$colorBg);
    //把原图copy到临时图片中
    @imagecopy($objTmpImg,$image,0,0,0,0,$imgWidth,$imgHeight);
    //创建要写入的水印文字对象
    $objText = $this->createText($this->Text);
    //计算要写入的水印文字的位置
    $x = 5;
    $y = $newHeight-5;
    //写入文字水印
    @imagettftext($objTmpImg,10,0,$x,$y,$color,$this->Font,$objText);   
    //生成新的图片,临时图片
    switch($imgType)
    {
         case 1:
              imagegif($objTmpImg,$tmpImg);
              break; 
         case 2:
              imagejpeg($objTmpImg,$tmpImg);
              break; 
         case 3:
              imagepng($objTmpImg,$tmpImg);
              break; 
         default:
              return;
              break;
    }   
    //释放资源
    @imagedestroy($objTmpImg);
    @imagedestroy($image);
    //重新命名文件
    if($this->OverFlag)
    {
        //覆盖原图
        @unlink($inImg);
        @rename($tmpImg,$outImg);
    }
    else
    {
        //不覆盖原图
        @rename($tmpImg,$outImg);
    }
}

//--------------------------------------
//功能:创建水印文字对象
//参数:无
//返回:创建的水印文字对象
function createText($instring)
{
   $outstring="";
   $max=strlen($instring);
   for($i=0;$i<$max;$i++)
   {
       $h=ord($instring[$i]);
       if($h>=160 && $i<$max-1)
       {
           $outstring .= "&#".base_convert(bin2hex(iconv("gb2312","ucs-2",substr($instring,$i,2))),16,10).";";
           $i++;
       }
       else
       {
           $outstring .= $instring[$i];
       }
   }
   return $outstring;
}

}//class
?>

 


<?php
$ch 
curl_init
();
curl_setopt($chCURLOPT_URL'http://www.111cn.net'
);
curl_setopt($chCURLOPT_HEADERtrue
);
curl_setopt($chCURLOPT_RETURNTRANSFER1
);
curl_setopt($chCURLOPT_NOBODYtrue
);
$order curl_exec($ch
);
echo 
''
;
echo 
strip_tags($order
);
echo 
''
;
curl_close($ch);?>


有的服务器是看不到了,原因要根据服务器的配置而定了,在这里我就不多说了.

[!--infotagslink--]

相关文章

  • 如何解决局域网内mysql数据库连接慢

    通过内网连另外一台机器的mysql服务, 确发现速度N慢! 等了大约几十秒才等到提示输入密码。 但是ping mysql所在服务器却很快! 想到很久之前有过类似的经验, telnet等一些服务在连接请求的时候,会做一些反向域名解析(如果...2015-10-21
  • MYSQL数据库使用UTF-8中文编码乱码的解决办法

    1.用phpmyadmin创建数据库和数据表 创建数据库的时候,请将“整理”设置为:“utf8_general_ci” 或执行语句: 复制代码 代码如下:CREATE DATABASE `dbname` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; 创...2015-10-21
  • PHP连接公司内部服务器的MYSQL数据库的简单实例

    “主机,用户名,密码”得到连接、“数据库,sql,连接”得到结果,最后是结果的处理显示。当然,数据库连接是扩展库为我们完成的,我们能做的仅仅是处理结果而已。...2013-09-29
  • 修改MySQL数据库中表和表中字段的编码方式的方法

    今天向MySQL数据库中的一张表添加含有中文的数据,可是老是出异常,检查程序并没有发现错误,无奈呀,后来重新检查这张表发现表的编码方式为latin1并且原想可以插入中文的字段的编码方式也是latin1,然后再次仔细观察控制台输...2014-05-31
  • mysql数据库中的information_schema和mysql可以删除吗?

    新装的mysql里面有两个数据库:information_schema 和 mysql 。他们是干么用的?可以删除么?当然是不可以删除的。 1.information schema 是mysql系统用的所有字典信息,包括数据库系统有什么库,有什么表,有什么字典,有什么存...2014-05-31
  • PHP利用XML备份MySQL数据库实例

    本文章来给大家介绍一个PHP利用XML备份MySQL数据库实例,这种方法个人认为只适用小数据量,并且安全性要求不高的用户了。 以下是在Linux下通过Apache+PHP对Mysql数据...2016-11-25
  • godaddy空间怎么创建mysql数据库 godaddy数据库创建方法

    godaddy空间算是一个在国内最受欢迎的国外空间了,小编为一朋友买了一个godaddy空间了,但绑定好域名与ftp之后发现数据库不知道如何创建了,下面经一朋友指点得到了解决办...2016-10-10
  • PHP实现MySQL数据库备份的源码

    对于拟虚空间我们肯定没有操作服务器的权限此时要备份数据库我们可以集成在网站后台来操作,下面一起来看一篇关于PHP实现MySQL数据库备份的源码教程,具体的如下所示。...2016-11-25
  • PHP连接MySQL数据库并向数据库增加记录

    首先需要通过PHP来连接MySQL数据库: #连接数据库 下面是最简单的PHP连接MySQL数据库的代码: 代码如下 复制代码 <?php $link=mysql_connect(...2016-11-25
  • php中实现mysql数据库备份与linux自动定时备份代码

    文章介绍了二种数据库备案的代码,一种是我们php写的常用的数据库备份类,另一种是为linux朋友提供的一个自动定时备份mysql数据库的代码,有需要的同学可以参考一下。...2016-11-25
  • php 列出MySQL数据库中所有表二种方法

    php教程 列出MySQL数据库教程中所有表二种方法 PHP代码如下: function list_tables($database) { $rs = mysql教程_list_tables($database); $tables = a...2016-11-25
  • php 导出.sql文件/mysql数据库备份程序

    <?php $database='';//数据库名 $options=array( 'hostname' => '',//ip地址 'charset' => 'utf8',//编码 'filename' => $database.'.sql',//文件名...2016-11-25
  • 更改Mysql数据库存储位置的具体步骤

    一.首先把mysql的服务先停掉。 二.更改MySQL配置文件My.ini中的数据库存储主路径...2013-09-26
  • php导入excel文件入mysql数据库例子

    php导入excel文件入mysql数据库我们是需一借助一个phpexcel类文件了,有了这个类文件我们就可以快速简单的导入excel到mysql数据库中,下面来给大家整理一个例子,希望能对...2016-11-25
  • php怎么打开数据库 Php连接及读取和写入mysql数据库的常用代码

    小编推荐的这篇文章介绍了Php连接及读取和写入mysql数据库的常用代码,非常实用,有兴趣的同学可以参考一下。 既然现在你看到了这篇文章,说明你肯定知道PHP和MySQL是...2017-07-06
  • php连接mysql数据库并查询记录所有记录

    下面是一款简单的php操作数据库的程序,我们是先讲php连接mysql数据库,然后再执行sql查询语句再把我们要的记录显示出来,最后关闭与mysql数据库的连接。 $host = 'lo...2016-11-25
  • 用PHP实现XML备份Mysql数据库

    以下是在Linux下通过Apache PHP对Mysql数据库的备份的文件代码: 文件一、Listtable.php (文件列出数据库中的所有表格,供选择备份) <html> <head> <title> 使用XM...2016-11-25
  • php与mysql数据库通信三步曲

    之前说过php跟js的最大的不同点就是能够直接与数据库打交道,存储信息,读取信息,与用户交互。这里总结了php连接数据库的比较全面和靠谱的三个步骤,简称三步曲。 主要...2016-11-25
  • PHP程序员的40点陋习

    Reinhold Weber 提出PHP程序员的40点陋习.(本E问只写了一部分内容,译者找到原版翻译,以下是完全版) 1不写注释 2不使用可以提高生产效...2016-11-25
  • 简单实用MySQL数据库PHP操作类

    下面是一个站长写的一个非常简单实用的数据库操作类了,这里面主要功能是数据库连接,查询数据,删除数据,更新数据等等,这个类的特点时不限制mysql而是直接执行由外部给出的...2016-11-25