Linux,Apache,Mysql,PHP
Can you Trust CHECK TABLE ?
Posted in LAMP on 2008/09/12 / 评论(0) »

Take a look at this:

SQL:
  1. mysql> repair TABLE a3;
  2. +---------+--------+----------+----------+
  3. | TABLE   | Op     | Msg_type | Msg_text |
  4. +---------+--------+----------+----------+
  5. | test.a3 | repair | STATUS   | OK       |
  6. +---------+--------+----------+----------+
  7. 1 row IN SET (0.10 sec)
  8. mysql> SELECT * FROM a3 ORDER BY i;
  9. +------------+
  10. | i          |
  11. +------------+
  12. | 2147483648 |
  13. |         11 |
  14. |         13 |
  15. |         14 |
  16. | 2147483647 |
  17. +------------+
  18. 5 rows IN SET (0.00 sec)

The sort order is obviously wrong while CHECK TABLE is not reporting any error

Why ? Because CHECK TABLE only looks at MyISAM data and Index files and it does not compare information in these to table definition (.frm file)

In this particular case I replaced .frm file for the table from different one changing INT to UNSIGNED INT to see what effect it will give - as you can see you get quite funny table which is considered OK by CHECK TABLE, which does store values larger than max signed int but which sorts them as unsigned ints. Quite fun.

I hope the task of fixing this is somewhere on MySQL roadmap

from

 新公司的系统一直很不稳定,店面销售人员经常报登不上系统或速度奇慢的情况,怀疑可能是代码存在数据库连接泄露及内存泄露现象,离春节只有几天时间,也来不急进行代码调优,只有从配置层面看有那些手段来采用,以便暂且缓解一下服务器压力,降低系统的故障率。为了第一时间能够知道服务器故障,基于nagios搭建了服务器监控程序,这样系统有故障时候,能够用短信方式通知系统故障,及时解决。

1、系统情况:

  操作系统:Redhat AS4

  数据库:mysql 4.1.18

  应用服务器:JBoss 3.2.7

  服务器: 4 x3.00GHz的Intel Xeon CPU

  数据库和应用服务器都部署在同一台服务器上。

  简单跟踪了一下,发现平常内存、io负载都不大,数据库连接数也不多。只是很奇怪的是mysql的cpu负载始终是99.9%,但整个系统的速度还行,开始怀疑是JVM、数据库参数、索引没有优化导致的,因此先着手对java虚拟机参数及数据库参数进行了调整。

2、java虚拟机调优

  • 调整虚拟机的参数

  JAVA_OPTS=”$JAVA_OPTS -Xms512m -Xmx1024m -server -XX:MaxPermSize=300m -XX:MaxNewSize=300m”

  • 调整jboss的数据库连接池,修改最大连接数及连接回收时间

<min-pool-size>20</min-pool-size>

<max-pool-size>300</max-pool-size>

<idle-timeout-minutes>1</idle-timeout-minutes>

<min-pool-size>20</min-pool-size>

3、数据库调优

  • 对所有的表,优化及增加索引。

发现一个好用的mysql工具navicat,感觉比ems 好用,用这东西增加索引方便多了。

  • 调整mysql参数

原来是基于my-medium.cnf 修改的参数,由于担心是大数据量查询sort区等不够及程序存在内存泄露问题,因此基于my-huge.cnf进行调整。

[client]
port            = 3306
socket          = /var/lib/mysql/mysql.sock
[mysqld]
port            = 3306
socket          = /var/lib/mysql/mysql.sock
skip-locking
key_buffer = 256M
max_allowed_packet = 1M
table_cache = 256
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 2M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 32M
thread_concurrency = 8
max_connections=300

#skip-networking

#log-bin

server-id       = 1

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash
#safe-updates

[isamchk]
key_buffer = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[myisamchk]
key_buffer = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

调整后,支撑了3天左右,除了mysql的cpu占用始终是99%外,系统整体运行基本正常,忙于其他事情,没有继续跟踪。没想到大年初一接了一堆报警短信,执行查看了系统参数,发现系统竟然没有swap区,欣喜一阵,可能是这原因吧,于是临时建立swap区。

4、增加swap区

  • 在/swap下生成1G的文件

     # mkdir /swap

  # dd if=/dev/zero of=/swap/swapfile bs=500M count=2

  • 创建为swap文件

  #mkswap /swap

  • 让swap生效

  #swapon /swap

  • 查看一下swap

  #swapon -s

  • 把新增的swap文件加到fstab文件中让系统引导时自动启动

  #vi /etc/fstab

  /swap/swapfile swap swap defaults 0 0

    增加后,重启应用及服务,mysql的cpu占用还是持续性为99.9%,而且运行上一段时间还是出现无法登录的情况。远程登录到系统,发现内存、io、swap区占用都很正常,数据库连接数也很正常,而且在停止mysql和jboss后,直接重启jboss,不能正常启动成功,需要等上一会儿,怀疑是文件句柄及tcp连接尚未正常释放。联系以前遇到的情况,怀疑与操作系统允许的最大句柄数有关。

用ulimit -a|grep open 命令查看了结果为:

open files                      (-n) 1024

用cat /proc/sys/fs/file-max查看结果为:

379816

由于数据库和jboss同时部署在同一台服务器上,在负荷较小的情况下用lsof -u root |wc -l查看root用户的句柄数仍然为700多,因此在负荷较高的情况下,用户的最大句柄数1024是有点小。

5、修改操作系统句柄数

5.1、修改操作系统的最大限制数

  • 修改 /etc/sysctl.conf

    增加fs.file-max = 8061540

  • 在/etc/pam.d/login 中添加  

    session     required      /lib/security/pam_limits.so

  • 在/etc/security/limits.conf 中添加
    root              -        nofile           1006154

  修改root用户的句柄数(包括hard和soft)限制为1006154

  • 修改 /etc/rc.local   添加
    echo 8061540 > /proc/sys/fs/file-max

5.2、修改用户最大限制数

考虑到重启服务器的风险,先暂时修改一下启动jboss的root用户的/root/.bash_profile,增加如下内容:

ulimit -n 65535

重启jboss和mysql。

连续观察了几天,发现cpu始终占用99.9%的情况解决掉了,继续观察中。

6、参考文档

http://www.bea.com.cn/support_pattern/Too_Many_Open_Files_Pattern.html

http://kbase.redhat.com/faq/FAQ_80_1540.shtm

来源

zend framework 1.6发布
Posted in LAMP on 2008/09/04 / 评论(0) »
Zend Framework 1.6于今天发布,可以在其官网下载 http://framework.zend.com/download/current/

该版本包括了一系列的新工具:

Zend_Tool
Lucene 2.3 Index File Format Support
Zend_Session save handler for Database Tables
Paginator Component
Figlet Support
ReCaptcha Service
Captcha Form Element
Zend_Config_Xml Attribute Support
Zend_File_Transfer Component
File Upload Form Element
Zend_Wildfire Component with FireBug Log Writer

与新版同时发布的还有Zend Framework文档的PDF版本,也可以在其官网找到 http://www.zend.com/community/downloads

php调用mysql存储过程和函数的两种方法

存储过程和函数是MySql5.0刚刚引入的。关于这方面的操作在PHP里面没有直接的支持。但是由于Mysql PHP API的设计,使得我们可以在以前的PHP版本中的mysql php api中支持存储过程和函数的调用。

在php中调用存储过程和函数的主要步骤

1。调用存储过程的方法。

a。如果存储过程有 IN/INOUT参数,声明一个变量,输入参数给存储过程,该变量是一对,
一个php变量(也可以不必,只是没有php变量时,没有办法进行动态输入),一个Mysql变量。

b。如果存储过程有OUT变量,声明一个Mysql变量。
mysql变量的声明比较特殊,必须让mysql服务器知道此变量的存在,其实也就是执行一条mysql语句。
输入 set @mysqlvar=$phpvar ;

c。使用mysql_query()/mysql_db_query()执行mysql 变量声明语句。
Mysql_query("set @mysqlvar【=$pbpvar】");
这样,在mysql服务器里面就有一个变量,@mysqlar。如果时IN参数,那么其值可以有phpar传入。

D。 如果时存储过程。

1。执行 call procedure()语句。

也就是mysql_query("call proceduer([var1]…)");

2. 如果有返回值,执行select @ar,返回执行结果。

Mysql_query("select @var)"

接下来的操作就和php执行一般的mysql语句一样了。可以通过mydql_fetch_row()等函数获得结果。

如果时函数。 直接执行 select function() 就可以了。

php调用mysql存储过程和函数的方法一:
$host=\"localhost\";
$user=\"root\";
$password=\"11212\";
$db=\"samp_db\";
$dblink=mysql_connect($host,$user,$password)
or die(\"can't connect to mysql\");
mysql_select_db($db,$dblink)
or die(\"can't select samp_db\");
$res=mysql_query(\"set @a=$password\",$dblink);
$res=mysql_query(\"call aa(@a)\",$dblink);
$res=mysql_query(\"select @a\",$dblink);
$row=mysql_fetch_row($res);
echo $row[0];


php调用mysql存储过程和函数方法二:此方法需要db_mysqli.dll的支持!
调用带有select语句的存储过程就出现 PROCEDURE p can’t return a result set in the given context的错误。Google了半天,在mysql官网上找到一些说法,db_mysql的模块不支持存储过程调用,解决方法是用db_mysqli。测试了一下,果然可以了。

用法比较简单,没啥好说的,从网上copy一段代码吧:
/* Connect to a MySQL server */
$link = mysqli_connect(
'localhost', /* The host to connect to */
'root', /* The user to connect as */
'root', /* The password to use */
'db_name'); /* The default database to query */
if (!$link) {
printf(\"Can't connect to MySQL Server. Errorcode: %sn\", mysqli_connect_error());
exit;
}
/* Send a query to the server */
if ($result = mysqli_query($link, \"call se_proc('crm')\")) {
/* Fetch the results of the query */
while( $row = mysqli_fetch_array($result) ){
echo ($row[0]. \"--------- SR. \" . $row[1] . \"
\");
}
/* Destroy the result set and free the memory used for it */
mysqli_free_result($result);
}
/* Close the connection */
mysqli_close($link);
?>
关于last_insert_id的值问题
Posted in LAMP on 2008/08/28 / 评论(0) »
last_insert_id产生的ID 每次连接后保存在服务器中。这意味着函数向一个给定客户端返回的值是该客户端产生对影响AUTO_INCREMENT列的最新语句第一个 AUTO_INCREMENT值的。这个值不能被其它客户端影响,即使它们产生它们自己的 AUTO_INCREMENT值。这个行为保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁或处理。

mysql的源代码里面,mysql_insert_id是这么定义的
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
{
  return mysql->;last_used_con->;insert_id;
}

MYSQL提供给c++,php等的API一般,有个MYSQL结构体。
结构体里面有insert_id, insert_id的类型 my_ulonglong。 其实就是long long.

每次mysql_query操作在mysql服务器上可以理解为一次“原子”操作, 数据库的写操作常常需要锁表的, 是mysql应用服务器锁表不是我们的应用程序锁表。


附上MYSQL结构体的定义。

 
typedef struct st_mysql
{
  NET           net;                    /* Communication parameters */
  gptr          connector_fd;           /* ConnectorFd for SSL */
  char          *host,*user,*passwd,*unix_socket,*server_version,*host_info,*info;
  char          *db;
  struct charset_info_st *charset;
  MYSQL_FIELD   *fields;
  MEM_ROOT      field_alloc;
  my_ulonglong affected_rows;
  my_ulonglong insert_id;               /* id if insert on table with NEXTNR */
  my_ulonglong extra_info;              /* Used by mysqlshow */
  unsigned long thread_id;              /* Id for connection in server */
  unsigned long packet_length;         
  unsigned int  port;
  unsigned long client_flag,server_capabilities;
  unsigned int  protocol_version;
  unsigned int  field_count;
  unsigned int  server_status;
  unsigned int  server_language;
  unsigned int  warning_count;
  struct st_mysql_options options;
  enum mysql_status status;
  my_bool       free_me;                /* If free in mysql_close */
  my_bool       reconnect;              /* set to 1 if automatic reconnect */
  
  /* session-wide random string */
  char          scramble[SCRAMBLE_LENGTH+1];
  
/*
   Set if this is the original connection, not a master or a slave we have
   added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
*/
  my_bool rpl_pivot;
  /*
    Pointers to the master, and the next slave connections, points to
    itself if lone connection.
  */
  struct st_mysql* master, *next_slave;

  struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
/* needed for send/read/store/use result to work correctly with replication */
  struct st_mysql* last_used_con;

  LIST  *stmts;                     /* list of all statements */
  const struct st_mysql_methods *methods;
  void *thd;
  /*
    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
    from mysql_stmt_close if close had to cancel result set of this object.
  */
  my_bool *unbuffered_fetch_owner;
} MYSQL;
分页: 1/19 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]