优秀范文
当前位置:首页 > 其他范文 > 优秀范文 > 列表页

mysql_fetch_assoc()读不到数据

小草范文网  发布于:2017-05-17  分类: 优秀范文 手机版

篇一:PHP与MySQL通讯那点事

PHP与MySQL通讯那点事(1)

在我们的一款WebGame的生产环境中,一次无意的strace抓包时,发现了php与mysql大量通讯的数据。这种情况,在游戏服务器刚启动时,是正常的,但如果是运行一段时间之后,出现大量SELECT的SQL查询,绝对是有问题的,而且,所操作的数据库并不是配置库,那意味着,我们程序员的程序出现了违规的操作。

在我们的一款WebGame的生产环境中,一次无意的strace抓包时,发现了php与mysql大量通讯的数据。这种情况,在游戏服务器刚启动时,是正常的,但如果是运行一段时间之后,出现大量SELECT的SQL查询,绝对是有问题的,而且,所操作的数据库并不是配置库,那意味着,我们程序员的程序出现了违规的操作。具体结果大约如下:

如上图所示,php持续接收读取进程内描述符为3的响应包数据,描述符为3的为php与mysql建立的TCP通讯链接,这点也可以从313行的SELECT语句来确认。(原始数据丢失了,我模仿了一条。所以是配置库的SQL语句)

这是什么程序,想实现什么逻辑?为何要取这么多数据?

跟着这里的SELECT的sql语句,我定位到了相应的程序段:

1. /*

2. ** 业务逻辑的代码

3. */

4. public function SItem($roleId,$baseId) {

5. //...

6. // ############写出下面这种代码的人都得死.##################

7. $this->dbrRole->select('*');

8. $this->dbrRole->from('role_items');

9. $this->dbrRole->where('role_id',$roleId);

10. $this->dbrRole->where('baseId',$baseId);

11. $result = $this->dbrRole->get()->row(); //看上去,这里好像正常,我们都以

为框架会给我们只取一条。

12. //...

13. }

我们从代码上来看,好像明白程序员想根据对应的role_id到role_items表里取一条想符合的数据,所以,他调用了row方法,来取一条。看上去,这里好像正常,我们都以为框架会给我们只取一条。但实际上,框架是如何处理的呢?

我们来看下框架的对应row方法的实现过程。对了,我们是CodeIgniter框架的一个较老的版本。

1. /*

2. ** 框架中,DB drive中,row相关方法的代码

3. **

4. */

5. public function row($n = 0,$type = 'array'){

6. if(!is_numeric($n)){

7.if(! is_array($this->_rowData)){

8. $this->_rowData = $this->rowArray(0);

9.}

10.if(isset($this->_rowData[$n])){

11. return $this->_rowData[$n];

12.}

13.$n = 0;

14. }

1

mysql

5. return ($type == 'object') ? $this->rowObject($n) : $this->rowArra

y($n);

16. }

17.

18. //继续跟进rowArray方法

19. public function rowArray($n = 0){

20. $result = $this->resultArray();

21. if(count($result) == 0){

22.return $result;

23. }

24.

25. if($n != $this->_current && isset($result[$n])){

26.$this->_current = $n;

27. }

28.

29. return $result[$this->_current];

30. }

31.

32. //继续跟进resultArray方法 ###这个方法是重点###

33. public function resultArray(){

34. if(count($this->resultArray) > 0){

35.return $this->resultArray;

36. }

37.

38. if(false === $this->resulter || 0 == $this->recordCount()){

39.return array();

40. }

41.

42. $this->_dataSeek(0);

43. while($row = $this->_fetchAssoc()){

44.$this->resultArray[] = $row; //###########这个数组每次都增加

_fetchAssoc()结果的内存大小数量#########################

45. }

46. return $this->resultArray;

47. }

48.

49. //继续跟进_fetchAssoc方法

50. /*

51. ** 对应driver的_fetchAssoc方法的代码

52. */

53. protected function _fetchAssoc(){

54. return mysql_fetch_assoc($this->resulter);

55. }

我们可以看到CodeIgniter框架的resultArray方法使用mysql(我们的php调用mysql的api用的是mysql函数,有点绕,后面解释)的mysql_fetch_assoc函数对缓冲区的数据进行遍历转换。将所有缓冲区的数据全部复制给$this->resultArray属性,再判断row方法中所需要的key的结果是否存在,再与返回的。 也就是说,框架层并没有只从mysql server(潜意识上的mysql server)那边取一条给我们调用者,而是取了所有结果,再返回一条。(先别喷,后面解释) 当然,CI这种做法,也不是错。但我觉得有更好的改进方法。

这个问题,我们组的dietoad (征婚) 发现了这个问题,并给了修复方案。有些同学认为,这是程序员的错,程序员的SELECT语句没有加limit来限制条数。这我绝对赞同,而且,觉得写出这种代码的人都得死。

1. 业务层:为这种业务需求的SQL语句加上limit限制

2. 框架层:框架对于这种需求,自动控制,发现这种情况,直接返回1条

对于解决方案1,我写了一个正则,匹配select()方法被调用之后,row()方法被调用之前,中间没有使用limit()方法的所有代码,结果,发现量并不小。后来,我们决定两种方案同时实施,防止第二种出现漏掉的情况。

dietoad给出如下改进:

1. /*

2. ** //改进为当_rowData不存在时,从_rowData的数量开始取,取小于$n条记录,避免 上

面 resultArray方法中从缓冲区取所有数据,复制双倍数据,占用内存的情况

3. */

4. public function row ($n = 0, $type = 'array')

5. {

6. if(isset($this->_rowData[$n]))

7. {

8.return $this->_rowData[$n];

9. }

10. if (! is_numeric($n))

11. {

12.return $this->rowObject($n);

13. }

14.

15. $ln=count($this->_rowData);

16. //继续上次位置

17. while($ln++<=$n&&$r=$this->_fetchAssoc())

18. {

19. $this->_rowData[]=$r;

篇二:mysql核心知识要点

1整体知识介绍:mysql基本操作和使用,mysql优化(索引,分表等),mysql部署(读写分离,负载均衡等)

数据库基本介绍:数据库概念,常用数据库,web应用三大软件分工,PHP动态语言特点(处理数据),数据的存放(脚本运行时和执行完毕),数据库系统

关系型数据库:概念(关系+二维表),教学系统实例,常见关系型数据库,关系型数据库特点(所有数据相同结构,没有数据也分配存储空间)

非关系型数据库:键值对型,常见非关系型数据库,非关系型数据库特点(内存运行,硬盘同步)

关系型数据库典型概念:行row(记录record),列col(字段field),SQL(概念,DDL,DML(DML+DQL),DCL)

Mysql基本介绍:mysql软件介绍(c/s结构),mysql操作步骤,客户端的工作,mysql单独安装,mysql目录及文件介绍,mysql服务端管理(服务和mysqld.exe),客户端连接服务端(连接认证,执行sql,退出)mysql服务管理(net,服务管理,mysqld.exe –defaults-file=my.ini路径)

Mysql数据对象:mysql服务器?数据库?数据表?字段

基本SQL操作:库操作(create[if not exists][charset,collation],库文件夹介绍,数据库命名规则,特殊名字处理;show[like pattern],通配符,查看库创建语句;drop;alter),表操作(表与字段的依赖性;create [engine,charset],表文件分析,表与库的关系,保留字冲突,从已有表创建[like];show[like pattern],查看表字段[desc/describe/show columns from tb_name],查看表创建语句;drop;alter [操作add/drop/modify/change][位置first after],rename to重命名;数据操作(insert into省略字段和选择字段;select from[where条件],=比较;delete from[where];update set[where];删除和更新不可逆)

字符集:快速解决问题(set names),字符集,mysql字符集(数据存储,数据传输),数据存储字符集(服务器端,库,表,字段,图解),字符集优先级(字段?表?库?服务器端),数据传输过程字符集(图解(客户端client?连接层connection?服务器?客户端result),character_set变量,set names分析)

校对集:字符比较(ASCII比较),校对集工作(查看show collation),校对集设置(表选项中collate=校对集),校对集命名规则(_bin二进制,_ci[case insensitive],_cs[case sensitive]),utf8&gbk(utf8不支持中文比较,gbk支持拼音),校对集后期修改无效

存储引擎:概览mysql存储引擎,主要引擎[InnoDB和MyISAM],引擎的未来发展,引擎区别(MyISAM[查询和新增,全文索引],InnoDB[更新和删除,事务,5.5之后全文索引],文件区别)

乱码问题解决:作图(浏览器—PHP--mysql)

字段(列)类型:mysql数据类型(数值型,字符串型,日期时间型),数值类型(整型[tinyint,smallint,mediumint,int,bigint],显示宽度,0填充,无符号;浮点型[float,double],语法float(M,D),浮点支持科学计数法;定点数[decimal(M,D)],定点与浮点的存储方式区别),字符串类型(char(L);varchar(L);text;char与varchar比较表,mysql记录总长限制,文本不受限制(10字节);枚举enum[值存储,2字节,单选,方便插入[数值或者字符串],从1开始];集合set[存储方式二进制,多选,8字节];二进制文本),日期和时间类型(datetime[格式,8字节存储,时间跨度9999];date[];time[时间间隔];year[1字节存储,跨度1900-2155或70-69];timestamp[标准整型存储,表现与datetime一致])

列属性(约束):NULL(概念[与PHP不同],语法NULL/NOT NULL),默认值(default,用法,

插入数据时使用default关键字),键(主键[primary key,唯一标识,设计表图解,主键优势,主键语法包括建表和修改,删除主键];唯一键[unique key,优点,增加包含建表时和修改表结构,删除唯一键平[只能通过删除索引方式]]),自动增长(auto_increment,常用主键ID),注释(comment,SQL通用注释语法[--空格,#,/*块注释*/])

关系:关系分类(1:N[学生与班级对应关系,设计];M:N[教师与班级对应关系,设计];1:1[学生与学生关系])

外键(约束):外键(foreign key,学生与班级关系,外键功能,外键定义[外键(逻辑上),外键约束(语法上)],增加外键[创建表时和修改表结构],约束作用,删除约束[约束名],增加约束名[constraint],约束对应的索引),外键约束(主表和从表,约束操作[严格控制restrict,置空set null,级联cascade],约束范围[删除和更新],外键支持[InnoDB,类型严格一致,置空操作字段必须可以为空])

范式:范式定义(Normal Format),范式等级(1到6),数据库范式(满足到第三等级),1NF(原子性),2NF(部分依赖,复合主键),3NF(传递依赖),范式有点(通用,减低数据冗余),逆规范化(设置必要数据冗余,效率与磁盘空间的对抗)

高级数据操作:插入数据(选择插入[insert into tb_name select子句],主键冲突[insert into … on duplicate key update],替换插入[replace into]),删除数据(搭配orderby和limit,清空表

[truncate],delete与truncate区别),修改数据(搭配orderby和limit),查询数据(select选项[all和distinct],字段列表[表达式,字段别名],from子句[多表,表别名,虚拟表dual],五子句[where,group by,having,order by,limit]),where子句(操作流程,mysql布尔类型和值,表达式[关系运算符 =,in和not in,between and和not between and,is null和is not null;逻辑运算符;like运算符,通配符;运算符优先级]),group by子句(分组统计,合计函数[count(对非空字段统计),max(),min(),sum(),avg()],grou_concat(字段)[分组专用字段连接],group by[排序asc|desc],多字段分组,回溯统计[with rollup]),having子句(与where功能相似,可以使用字段别名,可以使用合计函数,与where操作数据不同),order by子句(排序,多字段排序),limit子句(限制记录数,指定索引位置,分页)

联合查询:联合查询(union,结果间联合,条件简化,union选项[all和distinct],字段数量一致类型无所谓[原因,var_dump看结果],union的select子句分别排序[子句需要括号,需要配合limit])

作业:实现用户在浏览器端创建数据库,创建数据表

连接查询:概念,连接分类(内连接[inner join [on],参与连接数据都必须存在,where替代on,默认连接方式,连接原理,where与on的区别,using去重],外连接[left/right join on,参与连接的数据有对应不上[左外保留左表数据,右外保留右表数据],full全外mysql不支持,on和using使用],交叉连接[内连接的无条件模式],自然连接[natural [left/right] join,相当与其他连接使用using,不能使用on])

子查询:子查询概念,功能,子查询分类(位置分类[where,from,exists],返回形式分类[标量子查询[单一值,用于比较],列子查询[配合in和not in,any,all和some],行子查询[使用括号语法构建行],表子查询[典型from子查询]])

视图:概念(虚拟表),视图作用(查询数据,提供接口,隐藏真实数据),视图管理(创建

[create view as select子句],删除视图[drop view],修改视图[alter view v_name as select子句],查看视图[show create view v_name,查看视图字段,查看视图创建语句],视图算法[概念,合并算法merge,临时表temptable,未定义undefined,视图指定算法[create

algorithm=temptable view]])

数据备份还原:导出(select into outfile ‘路径’,导出文件不能重名,字段分隔符[fields terminated by,enclosed by,escaped by],记录分隔符[lines terminated by/starting by],导出文件编码),导入(load data infile ‘路径’ into table tb_name 选项)

数据备份:MyISAM备份,mysqldump(mysqldump客户端,语法,表备份[库 表 表/ -b 库],数据库备份),还原(source,mysql库名 表名 < sql文件)

事务:事务目的,事务操作(开启[start transaction],提交[commit],回滚[rollback],回滚点

[savepoint name,rollback to name]),事务基本原理(mysql执行SQL方式[执行+提交],默认自动提交autocommit),事务安全日志(保存事务执行中间结果ib_logfile,InnoDB支持事务),事务特点ACID(原子性[Atomicity,事务是整体],一致性[consistency,事务前后数据完整性一致],持久性[Durability事务一旦提交,数据改变永久],隔离性[isolation,多用户并发互不干扰,相互隔离])

触发器:概念,语法(创建[create trigger t_name 事件时机 事件类型 on 表 for each row],事件时机[before,after],事件类型[insert,delete,update],mysql不支持在同一事件上创建多个出发程序;删除[drop trigger t_name];获取触发程序相关记录[old,new],分支结构

[if 条件 then 代码 end if],多语句[begin,end],语句结束符)

变量:系统变量,自定义变量(set,使用变量,select into,变量赋值符[:=]),变量有效期,变量作用域

SQL函数:内置函数(substring,char_length,length,instr,lpad,insert,strcmp),自定义函数(概念,函数要素[函数名,参数列表,函数体,返回值],语法[创建create function f_name(参数列表) returns 返回值类型],调用函数[select f_name(参数)],分支结构,循环结构[标签],内部定义变量[全局变量@var,局部变量declare var],中断(leave,iterate)) 存储过程:概念,与函数的区别,语法(创建[create procedure pr_name(过程参数in out inout)],过程参数类型,过程调用call)

Mysql用户管理:root密码忘记(重装,mysql管理用户的表user),重置root密码(带参数重启服务[--skip-grant-tables],无密码登录,修改用户表root密码[update set],加密算法

[sha1,md5,password(),重启]),普通用户管理(创建用户[create user user_name[ identified by ‘密码’],用户名形式[username@host]],删除用户[drop user username@host]),设置用户权限(添加[grant 权限列表 on 表名 to 用户],权限列表,表名表示方法,特殊权限[all privileges],刷新缓存[flush privileges,flush tables],删除用户权限[revoke 权限列表 on 表名 from 用户])

索引:概念,mysql索引类型[主键索引,唯一索引,全文索引,普通索引,复合索引]

PHP操作mysql:PHP变身客户端,开启该扩展,典型扩展(mysql,mysqli,pdo-mysql),libmysql.dll(连接服务提供者),查看mysql是否加载(PHPinfo),PHP操作mysql(连接认证mysql_connect(),准备和发送sql语句mysql_query,处理执行结果mysql_fetch_assoc(),释放资源[结果集],关闭连接mysql_close()),mysql_query(mysql_query返回值[布尔型,结果集],有返回值的语句[select,show,desc],没有返回值的语句[insert,update,delete ,DDL]),其他常用函数(mysql_errno(),mysql_error(),常见处理方式,mysql_fetch_array(),mysql_fetch_row()的区别,mysql_data_seek(),Mysql_affected_rows,Mysql_insert_id)

功能:注册成功跳转,分页(一次性,limit)

篇三:mysql2

PHP操作Mysql

PHP操作mysql其实主要就涉及了PHP的几个函数。

操作顺序:

1、链接数据库(进入控制器) -u -p

2、选择我们要操作的数据库 use

3、执行MYSQL语句(取得结果集)sql语句insert sele

4、从结果集中取得数据

5、清空结果集

6、关闭数据库 quit exit \q

一、链接数据库:

mysql_connect(服务器:端口号(3306),root,密码);

首先,要用PHP函数对数据库进行操作,要先开启apache的扩展功能

1、将PHP.ini的extension_dir 修改为 extension_dir="ext的路径"

extension_dir = "F:\www\php\ext"

2、将extension=php_mysql.dll前面的分号去掉

3、对httpd操作

F:\www\apache\conf\httpd.conf

找到其中的LoadModule php5_,并在其后面加一句话:

PHPIniDir "C:\Windows\php.ini"

4、重启apache

注意! 实在加载不了mysql模块,在httpd.conf文件中在LoadModule后面加上

Loadfile "E:\webserver\php\php5ts.dll"

Loadfile "E:\webserver\php\libmysql.dll"

mysql_connect();

用法:mysql_connect("服务器名:端口号","用户名","密码");

解释:

1、服务器名默认是localhost,端口号是3306,通常省略端口号

2、用户名密码就是我们Mysql的用户名、密码

3、成功则返回一个数据库的标识,失败返回false

eg:mysql_connect.php (即时的链接)

如果链接成功,得到数据库链接标识“Resource id #2”

如果链接失败,

扩展:当页面需要频繁的进行数据库的访问时可以建立与数据库的持久连接来提高执行效率

mysql_pconnect() 常链接

二、选择数据库

mysql_select_db("数据库名","链接标识");

注意:

1、数据库名,必须是一个已经存在的数据库,如果数据库不存在返回false

eg:mysql_connect.php

//2、返回值:bool

三、执行SQL语句

mysql_query("执行的语句","链接标识");

mysql_query("set names utf8")

//设置数据库编码为utf8

// names 不是name

注意:

1、将SQL语句赋值变量写在query语句外面,使语句更清晰,可读性更强,便于查

找错误

2、sql语句不能以分号结束

3、mysql_query对select操作,执行成功返回的是一个资源标识符,如果执行失败,

返回的是false

(如果是查询语句,select该函数会返回一个资源类型变量,这个变量包含一个查询

结果)

$result = mysql_query("select * from student",$link);

4、对于其它类型的SQL语句(update\delete\insert),返回的是true或false,对于

非false的返回,意味着执行是合法的并能够被服务器执行,但这并不是说明任何有关的操作

影响到或者有返回的行数,很有可能一条成功的操作并未影响或者返回任何的行。

mysql_affected_rows(),该函数判断我的sql语句影响的行数 (不需要参数)

返回值:正数、0、-1

当确实有影响行数的时候 返回影响的函数

当语法正确但是没影响行的时候 返回的是 0

语法错误的时候 返回的是-1

取得前一次 MySQL 操作所影响的记录行数

insert delete updatde

注意:增删改查只有查(select)会返回资源类型,其余的返回的都是true false

四、取出数据(仅对查询语句有效)

mysql_fetch_array();

mysql_fetch_assoc();

mysql_fetch_row();

作用:从查询语句执行后得到的结果集中取出数据(一条记录)

$list=mysql_fetch_array($result):将result记录集中的第一个记录转换为既有关联又有索

引的数组,会出现两遍数据

其实array有第二个可选参数MYSQL_ASSOC、MYSQL_NUM、MYSQL_BOTH

$list=mysql_fetch_row($result):将result记录集中的第一条记录转换为索引数组

$list=mysql_fetch_assoc($result):将result记录集中的第一个记录转换为关联数组

mysql_fetch_assoc = mysql_fetch_array(,MYSQL_ASSOC)

mysql_fetch_row = mysql_fetch_array(,MYSQL_NUM)

注意:

1、三个函数返回的都是一维数组

2、mysql_fetch_array();返回的数组中,数组元素既有索引数组元素,又有关联数组的元

3、mysql_fetch_assoc();返回的是一个关联数组,键名对应数据表的属性名

4、函数每次只能从结果集中取出一条数据,也就是数据表中的一行,在取出一条数据

之后会将数据指针后移一位

5、如果想要将结果集中的所有数据都取出来,需要用到while循环

6、 mysql_affected_rows(),该函数判断我的sql语句影响的行数 (不需要参数)

取得前一次 MySQL 操作所影响的记录行数

insert delete updatde

7、mysql_num_rows()用来判断我select语句有没有查询的结果(需要参数结果集)

返回结果集中行的数目。

1.当从数据库中取出数据时,mysql_num_rows()函数返回符合查询条件的记录行数,如

果没有符合的,返回0。

2.当向数据库插入数据和更新某个记录的部分内容时,用mysql_affected_rows返回插入或者更新成功的行数。

五、清空结果集

mysql_free_result("结果集");

六、关闭数据库

mysql_close("链接标识符");

注意:1、mysql_close()只能用来关闭非持久的链接

mysql_errno()

mysql_error()

本文已影响