Posts Tagged 'mysql'

freebsd升級mysql client

一月19th, 2010

mysql serve 是5.1.x的,客戶端是5.0.x的,用phpmyadmin,總有一個提示,說版本不匹配,感覺不爽。
用Ports的方法升級客戶端,不行,報錯。 說5.1和5.0有衝突,只能先刪除。
用了portmaster -o databases/mysql51-client mysql-client-5.0.89
也不行。
加上export CONFLICTS=” 後執行,還是不行。看了
pkg_info mysql\*

Required by:
php5-mysql-5.2.12
php5-mysqli-5.2.12
因為還跑著網站,就沒敢貿然行事。
這天趁網站人少的時候,乾了一把刪除老的package
#pkg_delete -f mysql-client-5.0.89
到mysql5.1 client的目錄
#cd /usr/ports/databases/mysql51-client

#make install clean


等待。
好了看一下版本
#mysql -V
mysql Ver 14.14 Distrib 5.1.42, for portbld-freebsd8.0 (amd64) using 5.2
用portmaster升級2個有依賴的php組件
#portmaster php5-mysql php5-mysqli
等待。

重啟apache,好了。
出乎意料的是安裝過程中,php可以正常的鏈接mysql。 網站正常,還以為pkg_delete會刪除使用的so文件,導致網站出狀況。

感謝hshh

Popularity: 3%

用oracle的merge實現mysql的replace into

九月2nd, 2009

mysql有一個replace into的dml語句,類似insert,但是會在insert之前檢查表的唯一索引或主鍵。 如果存在,就改為update操作。
這在很多應用中是一個很常用的操作。 有了這個replace into ,就可以將一個select後判斷後做update or insert改為一句話,甚是方便。

oracle9以後(好像)有了merge into,也可以實現類似功能,sql demo如下

  1. merge into qq a
  2. using   ( select ' ' 2022 ' ' cname ' company_no , ' cname ' company_name from qq where 2 ) rownum < 2 ) b
  3. on   . company_no = b . company_no ) ( a . company_no = b . company_no )
  4. WHEN   MATCHED THEN
  5.   UPDATE   SET company_name = a . company_name || ' a ' a . company_name = a . company_name || ' a '
  6. WHEN   NOT MATCHED THEN
  7.   INSERT
  8.     . company_no , a . company_name ) ( a . company_no , a . company_name )
  9.   VALUES
  10.     . company_no , b . company_name ) ; ( b . company_no , b . company_name ) ;

Popularity: 27%

mysql裡面的oracle decode

八月26th, 2009

oracle裡面有一個decode的函數,顧名思義,可以將1,2,3按照需求轉成a,b,c,最後還有一個缺省值。

mysql裡面好像沒有這個函數。 但是可以用另外的函數來實現類似的效果。

IF(expr1,expr2,expr3)
如果expr1是TRUE(expr1<>;0且expr1<>;NULL),那麼IF()返回expr2,否則它返回expr3。 IF()返回一個數字或字符串值

oracle的寫法

SELECT decode(ttype,1,'a',2,'b',3,'c','d') FROM taba

可以在mysql裡寫成

SELECT if( ttype =1, 'a', if( ttype =2, 'b', if( ttype =3, 'c', 'd' ) ) )
FROM taba

Popularity: 29%

mysql load data infile

五月5th, 2008

如何提高mysql load data infile的速度 <br />測試數據2.5G,共有數據9427567條。 用的mysql的large服務器的配置。
load一次需要大概10分鐘左右。
建的表用的是MYISAM,調整了幾個session的參數值

SET SESSION 256217728 ; BULK_INSERT_BUFFER_SIZE = 256217728 ;
SET SESSION 256217728 ; MYISAM_SORT_BUFFER_SIZE = 256217728 ;

運行結果如下

Query OK, 9427567 rows affected, 1558 warnings (3 min 55.21 sec)
Records: 9427567 Deleted: 0 Skipped: 0 Warnings: 0
google到的還可以

set global 256217728 ; KEY_BUFFER_SIZE = 256217728 ;
alter table tablename disable keys ;

如何load數據裡面帶反斜杠(backslash)”\”的數據 <br />由於如果你沒有指定FIELDS子句,則默認值為假設您寫下如下語句時的值:
FIELDS TERMINATED BY '\t' ENCLOSED BY ” ESCAPED BY '\\'
所以,如果你的數據裡面有反斜杠(backslash)”\”的時候,數據會出現被截斷的問題。 出現這種問題,只要寫上如下的fields子句即可
FIELDS TERMINATED BY '\t' ENCLOSED BY ” ESCAPED BY ”

如何load不同編碼的數據 <br />原來用的4.X的mysql,我是select INTO OUTFILE ,只後用iconv,或者其他軟件來做。 可以參考這裡 ,但是由於這次數據大,用ultraedit等軟件打開都要半天。 好在新版的mysql可以增加一個新的參數
CHARACTER SET gbk
我的文本數據是GBK的編碼,數據表是utf8的,用這種方法測試成功。
如何load的時候只insert特定的列 <br />比如表裡面有比元數據多的列。 可以在load的時候指定要插入的字段名字。

示例的代碼如下:

LOAD DATA INFILE ' ' ~/data.txt '
INTO TABLE fb0505
CHARACTER SET   gbk
FIELDS TERMINATED BY ' ' \t ' ENCLOSED BY '' ESCAPED BY ''
LINES TERMINATED BY ' ' \n ' STARTING BY ''
, fb_type , fb_date , item_url ) ; ( seller_id , fb_type , fb_date , item_url ) ;

其中表fb0505裡面還有一列是id。

Popularity: 27%

mysql去除特殊asc碼

七月22nd, 2007

要做一個mysql數據導入並且更新的工作。 數據源是excel裡來的。
選中excel裡面左上角的元素,ctrl+shift+end,選中全部有內容的cell。 另存為一個abc.txt的文件。
數據只有2列,建了一個有2列的表,準備把數據load進去,用root用戶登錄的,在mysql的shell運行如下命令
load data infile '/root/test.dat' into table mytable FIELDS TERMINATED BY '\t';
結果報錯。
ERROR 13 (HY000): Can't get stat of '/root/test.dat' (Errcode: 13)
後來google,說是權限的問題,看來可能是mysql不能讀root目錄下的文件,隨便換了個目錄,問題解決。
load data infile '/tmp/test.dat' into table ppname FIELDS TERMINATED BY '\t';
但是後來出現的問題,基本讓我崩潰。
舉個例子

select * from mysql > select * from mytable ;
+------+------+
| b | | a | b |
+------+------+
| aaa | aaa | aaa
+------+------+
1 row in set ( 0.00 sec )

肉眼看上去,a和b是一樣的,然後我就按照一樣的去匹配,奇怪的是怎麼做都不行,剛開始以為是大小寫的問題,作了lower操作還是不行。
後來開始不相信自己的眼睛了,查看一下到底是什麼

select mysql > select a ) , hex ( b ) hex ( a ) , hex ( b ) from mytable ;
+--------+----------+
( a ) | hex ( b ) | | hex ( a ) | hex ( b ) |
+--------+----------+
| 6161610 D | | 616161 | 6161610 D |
+--------+----------+
1 row in set ( 0.00 sec )

這個時候才發現每個字符後邊多了一個
0D
被這個問題搞了個把鐘頭,鬱悶的要死。 做了以下處理,終於烏雲散盡看見陽光了。
update mytable set b=UNHEX(TRIM(TRAILING '0D' FROM hex(b)));

奇怪的是我模擬不出來這種數據,本來以為是沒有加“LINES TERMINATED BY '\n'”的問題,可是後來加了也不行,:S
看來眼見不一定為實啊。

Popularity: 18%

用mysqldumpslow分析mysql的slow query log

六月7th, 2007

mysql有一個功能就是可以log下來運行的比較慢的sql語句,默認是沒有這個log的,為了開啟這個功能,要修改my.cnf或者在mysql啟動的時候加入一些參數。 如果在my.cnf裡面修改,需增加如下幾行

long_query_time = 1
log-slow-queries = /var/youpath/slow.log
log-queries-not-using-indexes

long_query_time 是指執行超過多久的sql會被log下來,這裡是1秒。
log-slow-queries設置把日誌寫在那裡,可以為空,系統會給一個缺省的文件host_name -slow.log,我生成的log就在mysql的data目錄
log-queries-not-using-indexes 就是字面意思,log下來沒有使用索引的query。

把上述參數打開,運行一段時間,就可以關掉了,省得影響生產環境。

接下來就是分析了,我這裡的文件名字叫host-slow.log。
先mysqldumpslow –help以下,俺主要用的是
-s ORDER what to sort by (t, at, l, al, r, ar etc), 'at' is default
-t NUM just show the top n queries
-g PATTERN grep: only consider stmts that include this string

-s,是order的順序,說明寫的不夠詳細,俺用下來,包括看了代碼,主要有
c,t,l,r和ac,at,al,ar,分別是按照query次數,時間,lock的時間和返回的記錄數來排序,前面加了a的時倒敘
-t,是top n的意思,即為返回前面多少條的數據
-g,後邊可以寫一個正則匹配模式,大小寫不敏感的

mysqldumpslow -sc -t 20 host-slow.log
mysqldumpslow -sr -t 20 host-slow.log

上述命令可以看出訪問次數最多的20個sql語句和返回記錄集最多的20個sql。
mysqldumpslow -t 10 -st -g “left join” host-slow.log
這個是按照時間返回前10條裡面含有左連接的sql語句。

用了這個工具就可以查詢出來那些sql語句是性能的瓶頸,進行優化,比如加索引,該應用的實現方式等。

Popularity: 29%

apache child pid exit signal File size limit exceeded error

五月25th, 2007

一個正常使用的網站,LAMP架構,突然打不開了,但是另外一個二級域名的網站,在同一台服務器上可以打開,靜態文件也可以打開,因為出故障前有段時間程序沒有更新,程序錯誤的可能性不大。
telnet 到網站的80端口,也可以打開,現像很奇怪。
重起了apache,沒用,mysql用命令行也可以使用,沒問題,一時沒了方向。
於是tail了apache的log,一個是正常的web log,一個是error_log。
觀察之後,發現了異常現象,apache的error_log一直輸出錯誤信息如下:

[Thu May 24 23:11:27 2007] [notice] child pid 23406 exit signal File size limit exceeded (25)
[Thu May 24 23:12:01 2007] [notice] child pid 23544 exit signal File size limit exceeded (25)
[Thu May 24 23:12:47 2007] [notice] child pid 23633 exit signal File size limit exceeded (25)
[Thu May 24 23:12:53 2007] [notice] child pid 22799 exit signal File size limit exceeded (25)

說有文件大小超過了限制。
google了一下,說是超過了apache 2G的文件限制,試用find命令在系統裡面查找超大的文件

find / -size +1000000k

查找到2個文件,一個是

/xxx/xxx/page_parse_time.log
/xxx/yyy/support-popbytes_log

第一個文件page_parse_time.log的大小在2G左右,壓縮備份後,

> /xxx/xxx/page_parse_time.log

,問題解決。
page_parse_time.log的文件內容是程序記錄sql query的log以及執行時間的log,每個頁面請求都會寫上一些數據,這麼超過2G也不奇怪了。

上次還遇到過一次mysql數據條數過多,的問題報錯信息如下:

LOGSQL Insert insert Failed : insert into adodb_logsql , sql0 , sql1 , params , tracer , timer ) ( created , sql0 , sql1 , params , tracer , timer ) values ( ,?,?,?,?,? ) NOW () ,?,?,?,?,? ) The table ' ' adodb_logsql ' is full

經查

select mysql > select * ) count ( * ) from adodb_logsql ;
+----------+
( * ) | | count ( * ) |
+----------+
| | 33127244 |
+----------+

3千萬,,,可能是有點大了,最後truncate了這個表,問題解決可是最後查mysql的文檔,關於Scalability and Limits部分沒有說mysql最多可以存多少條記錄,估計跟表的類型也相關。 原文說的是
Handles large databases. We use MySQL Server with databases that contain 50 million records. We also know of users who use MySQL Server with 60,000 tables and about 5,000,000,000 rows.
只是不知道它說的50 million是一個database裡面的所有記錄還是所有表的記錄加起來。 後邊的應該是所有60,000個表加起來的數據量。
————————
結論,必要的日誌是需要的,但是要控制大小,有循環機制,或者有監控機制,切記,切記。

Popularity: 32%

discuz mysql數據庫編碼轉換latin1->utf8

三月13th, 2007

幫朋友的論壇做了一次編碼轉換的工作。 系統是windows 2003,mysql4.1 discuz 5
本來以為很簡單,dump數據
mysqldump -u root -p –opt –default-character-set=latin1 \
–skip-set-charset olddb cdb_members > d:\bak\cdb_members.sql
出來,用工具轉一下編碼,然後再導入
mysql -u root -p –default-character-set=utf8 newdb < d:\bak\cdb_members.sql

實際操作並沒有想像的那麼簡單,最後解決的方案,也不是那麼複雜。
» More: discuz mysql數據庫編碼轉換latin1->utf8

Popularity: 31%

mysql tips

三月10th, 2007
  • 運行在文本文件裡的sql語句

shell> mysql db_name < text_file

還可以用一個USE db_name語句啟動文本文件。 在這種情況下,不需要在命令行中指定數據庫名:

shell> mysql < text_file

如果正運行mysql,可以使用source或\.命令執行SQL腳本文件:

mysql> source filename

mysql> \. filename

Popularity: 16%