MySQL

By admin, 12 十二月, 2016

一直以来我都没有考虑过些SQL语句是需要自己处理锁的问题。最近一段和钱有关的代码收到攻击才让我意识到问题的严重性。

受攻击的代码大概是这样子的:

 

SQL查询余额

if (余额 > 0) {

  执行提现操作

  减去余额

}

攻击者同时发送了多个提现请求,提现请求在判断是否有余额的时候都显示有余额,然后都允许提现。事实上,这里面其中一个请求提现完之后就不够余额了,但是其它进程都不知道这个情况。要避免这种情况的发生,需要对查询余额和扣减余额的操作做成原子操作,在查询和扣减操作之间不允许余额再发生变动。

标签

By admin, 22 九月, 2015

MySQL 5.6开始默认打开innodb_file_per_table参数,它会在/var/lib/mysql/dbname里创建很多很大的idb文件,它们是数据库的数据文件。如果不打开这个参数,所有数据库的数据都会存放在ibdata1一个文件里,可能导致这个文件非常大。

打开这个参数总体上是好的,它可以减少ibdata1的体积,不至于总写读写一个文件,分散存储可能会降低磁盘算坏的几率以及损坏后的损失可能会降低。

不过这个参数有一个缺点,它会令mysql数据目录总大小变成之前的2-3倍。

标签

By admin, 26 五月, 2015
  1.  找到my.ini(或my.cnf)
  2. 找到my.ini里面的[mysqld]一行
  3. 在[mysqld]下一行插入skip-grant-tables,保存
  4. 重启mysql服务器,此后访问mysql无需授权,什么密码都行

 

如果你的mysql服务器可以被远程访问,那么还是重新设一个密码比较好,在可以运行SQL语句的地方(mysql命令行或phpMyAdmin里的SQL运行页面)运行:

 

UPDATE mysql.user SET Password=PASSWORD('new_password') WHERE User='root';

FLUSH PRIVILEGES;

标签

By admin, 19 五月, 2015

weike_student_wrong_questions表大概有150万行数据,其中(tid, cid)做了索引,weike_exam_files不到100行,tid做了索引。下面一条语句执行时间大概是1.3秒。

 

SELECT weike_student_wrong_questions.tid, name, exam_time,
update_time, cid
FROM weike_student_wrong_questions
INNER JOIN weike_exam_files
ON weike_student_wrong_questions.tid = weike_exam_files.tid
GROUP BY weike_student_wrong_questions.tid, cid
ORDER BY exam_time DESC, cid;

把语句换成下面之后,查询效率大概提高了1000倍。 

     

标签

By admin, 14 五月, 2015

A friend of me asked me long time ago: "How can I have a ranking on a result with MySQL?". Now I found some time to write it down:

Lets do first some preparation for the example:

CREATE TABLE sales (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
, fruit VARCHAR(32)
, amount DECIMAL
);

INSERT INTO sales
VALUES (NULL, 'apple', 12.75), (NULL, 'orange', 1.89), (NULL, 'pear', 19.23)
, (NULL, 'banana', 4.25), (NULL, 'cherry', 123.75), (NULL, 'plum', 23.15)
;

Now lets query:

标签