ssh连接到ubuntu不能输入中文的问题

最近装了台ubuntu server做虚拟机,与字符集有关的各种配置都选用了utf8.

ssh连接上去之后,在shell中无法输入中文,复制粘贴也不行,SecureCRT和Bitvise Xterm都是如此。putty没有试过。

在vim中却可以输入中文,写代码虽然不受影响,但是要在shell中grep/ack的时候就有点郁闷 。

一次偶然的机会,为了解决perl 对于locale的报错, 竟然搞定了这个问题。

 

modify@ubuntu:~/apps/6$ ack "template_c" -w
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
 LANGUAGE = "zh_CN:zh",
 LC_ALL = (unset),
 LC_PAPER = "zh_CN",
 LC_ADDRESS = "zh_CN",
 LC_MONETARY = "zh_CN",
 LC_NUMERIC = "zh_CN",
 LC_TELEPHONE = "zh_CN",
 LC_IDENTIFICATION = "zh_CN",
 LC_MEASUREMENT = "zh_CN",
 LC_TIME = "zh_CN",
 LC_NAME = "zh_CN",
 LANG = "zh_CN.UTF-8"
 are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
application/smarty/change_log.txt
848:-improvement not to delete files starting with '.' from cache and template_c folders on clearCompiledTemplate() and clearCache()
modify@ubuntu:~/apps/6$
modify@ubuntu:~/apps/6$
modify@ubuntu:~$ sudo apt-get install language-pack-zh*
modify@ubuntu:~/apps/6$
modify@ubuntu:~/apps/6$ ack "template_c" -w
application/smarty/change_log.txt
848:-improvement not to delete files starting with '.' from cache and template_c folders on clearCompiledTemplate() and clearCache()




重启之后,就可以正常输入中文了….

代价是:

modify@ubuntu:~/apps/6/$ ll
ls: 初始化月份字符串出错
总用量 60
drwxr-xr-x 15 modify modify 4096 3�� 19 18:58 ./
drwxr-xr-x 8 modify modify 4096 3�� 25 11:07 ../
Posted in linux | Tagged , | Leave a comment

高性能mysql第三版第12-16章读书笔记

高性能mysql第三版第12-16章读书笔记

12.3.1提升平均失效时间(MTBF)

尽责地做好一些应做的事情:(在precona网站上有两份白皮书,更详细)
测试恢复工具和流程,包括从备份中恢复数据
遵从最小权限原则
保持系统干净,整洁
使用好的命名和组织约定来避免产生混乱
谨慎安排升级数据库服务器
在升级前,使用pt-upgrade之类的工具检查系统
确认基本的服务器配置是正确的
skip_name_resovle
除非能证明有效,否则禁用查询缓存
避免使用复杂的特性,比如复制过滤和触发器,事件。
监控重要的组件和功能,比如磁盘空间和RAID
尽量记录服务器的状态和性能指数,如果有可能尽量久地保存。
定期检查复制完整性
将备库设置为只读,不要让复制自动启动
定期进行查询语句审查
归档并清理不需要的数据
为文件系统保留一些空间。 比如创建一个巨大的空文件,在文件系统快满时,再将其删除。
养成习惯,评估和管理系统的改变,状态以及性能信息。

12.3.2 降低平均恢复时间(MTTR)

人的因素很重要。

12.4.1 共享存储或磁盘复制

DRBD看起来不错,但是会影响写入的性能,与myisam配合也比较吃力。
倾向于使用DRBD复制存放二进制日志的设备。如果主库挂掉,可以在被动节点上开启一个日志服务器,然后对失效主库的所有备库应用这些二进制日志。

 

13.1 云的优点缺点和相关误解

云并不能保证100%可用性,它也会出故障。今天又见故障啊。。
云的性能不太好把握,因为无法接触到底层的硬件。

13.2 mysql在云端的经济价值

云也适合运行不是很重要的基础设施,比如集成环境,开发测试平台,以及评估环境,事实上,我们正是这样做的。

 

14.4 拓展mysql

编写自己的存储引擎。

15.4.2 安全地清除老的二进制日志

不要删除文件了。。即使手动修改mysql-bin.index也不行。

mysql -e “PURGE MASTER LOGS BEFORE CURRENT_DATE – INTERVAL N DAY”;
expire_logs_days

15.5.2 文件系统快照

典型场景: 在升级前创建一个镜像,如果升级后有问题,只需要回滚到该镜像。
可以对任务不确定和有风险的操作都这么做,例如对一个巨大的表做变更。

但是快照并不是备份,它只是减少必须持有锁的时间的一个办法,释放锁后,必须人工复制文件到真正的备份中。

LVM快照使用写时复制copy-on-write的技术来创建快照。。。所以速度极快。。。
原始数据有变化时,LVM在任何变化发生之前,把受影响的块复制到快照预留的区域中。

15.6 从备份中恢复

在恢复过程中,保证mysql除了恢复进程外不接受其他访问。 –skip-networking
–socket=/tmp/mysql_recover.sock

如果备份做过压缩,那么不要分别解压和加载,应该在单个操作中完成:
gunzip -c xxxx.gz |mysql
gunzip -c xxxx.gz |grep “INSERT INTO `actor` | mysql sakila

使用日志服务器进行恢复:
将需要恢复的服务器叫做S1
在另外一台S2上恢复昨天的备份。
修改s2的配置: replicate-do-table = sakila.payment
重启s2,用change master to 来让它成为日志服务器的备库
检测s2上的show slave status的输出是否正确。
找到二进制日志中drop table的位置,在s2上执行start slave until来重放事件直到该位置。
在s2上stop slave.
将payment表从s2复制到s1.

只有没有任何多表的update,delete,insert操作这个表时,上述流程才是可行的。

15.6.5 INNODB崩溃恢复

关闭硬盘驱动器本身的回写缓存。
如果raid卡没有电池备份单元,那么也不要打开它的回写缓存。
回写缓存会导致数据只是写入到回写缓存而并没有写入磁盘的时候,就说fsync()已经完成。

修复二级索引:
optimize table
或者删除、重建表
也可以将表改为 myisam再改回来。
innodb_force_recovery
设置到4,对数据都没有损害(若有数据页损坏,将会丢失一些数据),但可能失去修复问题的机会,设置为5和6会更主动地修复问题,但损害数据的风险也会很大。
percona innodb recovery toolkit 可以从表空间的数据文件里直接抽取数据。

15.7 备份和恢复工具

mylvbackup
mydumper
mysqldump –tz-utc 使用户能在具有不同时区的服务器之间移动数据。

 

16.4 监测工具

需要二种类型的监测工具:
1) 健康监测工具,告警
2) 为趋势,诊断,问题排查,容量规划等记录指标的工具。

使用这些系统都像是把一个圆形的钉子钉到了一个方形的洞里….

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第11章读书笔记

高性能mysql第三版第11章读书笔记

11.2.3 向上扩展

即垂直扩展,使用性能更强的硬件。
mysql使用硬件的收益递减点大概是256G内存,32核CPU以及一个PCIe flash硬盘。
在更强大的服务器上,可以运行多个mysql实例(记得绑定到特定的CPU核心上, howto)。

 

11.2.4 向外扩展

即水平扩展:复制,(按功能)拆分,数据分片(sharding).

分片的二种方法:
固定分配 :
比如哈希或者取模。
动态分配 :
建立数据单元和分片的映射关系,比如向user表中增加一个shard_id列用于存储分片号,可以对数据存储位置做细粒度的控制。
也可以把shard_id放在user_id(big int)的高8位。
当一个分片快满时,可以设置一个标志位,告诉应用不要再往这里放数据了,如果未来分片中又有空间了,可以直接把标记位清除。

动静组合:
比如储存URL信息, 如果在映射表中存储URL,数据量就会太大了。
可以先将URL哈希到固定数目的桶中,然后用映射表维护桶与分片的对应关系。
也可以将桶作为对象的一部分进行编码。

11.2.7 向内扩展

即归档和清理。
将表划分为几个部分:
1) 比如user表可以划分为active_user和inactive_user。虽然数据库本身是可以缓存热数据的,但是innodb每次的缓存单位是page..
而一个page里面又保存有多条user记录。
2) 基于时间的数据分区。
新数据进入活跃节点,该节点硬件性能更好,另外一个节点存储旧数据,使用大而且较慢的硬盘。
映射关系可以如下设计:
create table users (
user_id int unsigned,
shard_new int unsigned,
shard_archive int unsigned,
archive_timestamp timestamp comment ‘归档时间’,
primary key (user_id)
);

然后使用一个归档的脚本,周期性地把旧数据从活跃节点转移到归档节点。

11.3.1 直接连接

复制上的读写分离:
1) 最简单的就是基于查询分离: 将不能容忍脏数据的读和写分配到主库。代价就是备库的使用率偏低,因为只有很少的查询能容忍脏数据。
2) 基于会话分离:用户不需要看到其他用户的最新数据,但需要看到自己的更新。可以在会话层设置一个标志位,表示做了更新,将该用户的查询在一段时间内总是指向主库。
甚至还可以去监视复制的延迟,如果用户在10秒前更新了数据,而备库延迟在5秒内,就可以安全地从备库中读取。要为整个会话选择同一个备库。
3) 基于版本或时间戳,通过从备库读取对象的版本、时间戳来判断数据是否足够新。
新的mysql服务器加入到负载均衡中去,需要先预热。
不必过早地进行分片,有时候可以试试直接升级硬件哈。

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第10章读书笔记

高性能mysql第三版第10章读书笔记

10.1.2复制如何工作

1) 主库把数据更改记录到binary log中,这些记录被称为二进制日志事件
2) 备库的IO线程将主库上的日志复制到自己的中继日志中,主库会启动binlog dump线程与之配合。
如果有多个备库,dump线程会成为主库的负担。
3) 备库的SQL线程读取中继日志中的事件,将其重放到备库数据之上。
这些线程都可以在show processlist时看到。

mysql会按照事务提交的顺序来记录二进制日志,而非每条语句的执行顺序。在记录二进制日志后,主库会告诉存储引擎,可以提交事务了。

10.2.1 创建复制帐号

在每台服务器上都创建复制帐号,便于交换主备库的角色。
grant replication slave, replication client on *.* to …..
replication slave用于复制。
replication client用于监控和管理复制 : show master status , show slave status.

10.3.6 复制过滤器

在主库上慎用 binlog_do_db和binlog_ignore_db,比如在use db和 delete from db.table的时候(即默认数据库与目标数据库名不相同的时候)。

10.4.1一主库多备库

使用场景:
1) 为不同的角色使用不同的备库(例如添加不同的索引或使用不同的存储引擎)
2) 把一台备库当作待用的主库
3) 将一台备库放到远程数据中心,用作灾难恢复
4) 延迟一个或多个备库,以备灾难恢复
5) 使用其中一个备库,作为备份,培训,开发或者测试或者在线分析的服务器。

 

10.4.6 主库,分发主库以及备库

如果需要多个备库,一个好办法是从主库移除负载并使用分发主库。
分发主库事实上也是一个备库,它的唯一目的就是提取和提供主库的二进制日志。其它的备库连接到分发主库,使得原来的主库摆脱了负担。
为了避免在分发主库上做实际的查询,可以将它的表修改为blackhole存储引擎。
分发主库也可以作多个,或者金字塔状。
设置slave_compressed_protocol来节约主库带宽,对于跨数据中心复制很有好处。
blackhole会有bug….
确保分发服务器上的每个表都是blackhole引擎,否则……
如果要对复制进行过滤或者重写,显然在分发主库上完成更加合理。

10.4.8 定制的复制方案

选择性复制: 每个备库只拥有主库的一部分数据。
备库通过replicate_wild_do_table来限制给定数据库的数据:
replicate_wild_do_table = sales.%
也可以用分发主库进行分发。

10.6.2 测量备库延迟

seconds_behind_master是通过将服务器当前的时间戳与二进制日志中的事件的时间戳相对比得到的,但是有很多意外会使它显示为null或者0。
替代品:pt-heartbeat
如果能在主库调用一个时间函数,写入一个时间戳,然后让此语句复制到备库,会在备库上写入一个不同的时间戳,那么只要比较这二个时间戳之间的差距即可。

 

10.6.5 改变主库

把备库提升为主库后,需要stop slave, change master to master_host=”, reset slave.

10.7.4 不确定语句

update limit …取决于查找行的顺序
在一个拥有多个唯一索引的表上使用replace或者insert ignore,取决于选择哪一个唯一索引。

10.7.10 丢失的临时表

临时表与基于语句的复制方式是不相容的,指的是如果备库重启,之前创建的临时表会消失。
所以在关闭备库之前,需要先stop slave,然后检查 slave_open_temp_tables 是否为0。为0的话就可以关闭了。

10.7.13 在主主复制结构中写入两台主库

1) 使用auto_increment_increment和auto_increment_offset
2) 创建一个多个列的主键,第一列使用服务器ID值。代价是主键变大了。
3) 仍然使用一个列的主键,在主键的高字节位存储服务器的ID。
4) 使用一个全局的独立ID生成器,且保证生成出来的不要太大了。。int bigint就好
4.1)  在一个全局数据库节点中创建一个包含自增列的表,通过此表生成唯一数字。
4.2)  使用memcached的incr()函数。
4.3)  批量分配。 比一个全局节点中请求一批数字,用完后再申请。
4.4)  uuid_short();

尽量避免这样搞吧。

 10.7.14 过大的复制延迟

有一些复杂的写操作可以临时在备库上完成,然后再把结果集写回到主库:

比如  insert into table select xx from tbl2 group by col2.

如果在主库上执行,那么每个备库将同样也要来一次这个group by ,会很慢。

可以在备库上创建一个特别保留的数据库,然后执行此查询,再把结果集select into outfile然后回到主库load data infile即可。

 

或者也可以分析为二步操作,一步是在主库上select into outfile,然后二步是在主库上load data。。这样才对嘛。。

 

话说很久没有管理VPS了,最近发现经常负载高到20以上,vmstat中blocked的进程一直在10左右, show processlist里面有很多locked的线程,集中在一张用户表上,数据量在100万左右,这么牛X的网站,每天的访问量只有500IP。。。 然后把此表从myisam改成innodb,
问题全部解决。 show processlist为空, 系统负载降到 0.5

 

 

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第9章读书笔记

高性能mysql第三版第9章读书笔记

9.4.7 什么时候应该使用闪存

固态存储最适合使用在任何有着大量随机IO工作负载的场景下。随机IO通常是由于数据大于服务器的内存导致的。用标准的硬盘驱动器,受限于转速和寻道延迟,无法提供很高的IOPS.

单线程工作负载是另一个闪存的潜在应用场景,因为单线程对延迟相当敏感。

在标准硬盘上存放日志文件通常是一个更好的主意,闪存连续写不比标准硬盘快多少。

9.4.9优化固态存储上的mysql

增加Innodb的IO容量:
增加读写线程数到10或15,也可以在2000~20000范围内调整innodb_io_capacity。

让innodb日志更大:
崩溃恢复时需要随机IO操作,会导致恢复需要很长一段时间,mysql数据文件保存在闪存上的话,可以让这个过程更快。
所以可以设置为4GB或更大。

把一些文件从闪存转移到RAID:
把innodb日志文件从数据文件中拿出来,单独放到带有电池保护写缓存的raid级上而不是固态设备上。
二进制日志和ibdata1(里面有双写缓冲与插入缓冲)也可以放到RAID上面。

禁用预读:
有个参数可以达到此效果。

配置Innodb刷新算法:
innodb_adaptive_checkpoint 设置为 keep_average
innodb_flush_neighbor_pages 设置为0.

禁用双写缓冲(慎重):
O_DIRECT与XFS,然后在iddata1中禁用双写缓冲,在某些设备上可以做到16KB的原子写入。
可以显著提升写入的性能,但是不保证100%安全。
限制插入缓冲的大小:
插入缓冲(变更缓冲)用于减少当更新行时不在内存中的非唯一索引引起的随机IO,但是对闪存没必要。

尝试不同的pagesize

innodb 页面校验的替代算法:
当IO写入非常快的时候,计算checksum的CPU耗时就比较突出了。

9.6.3 RAID配置和缓存

RAID条带化大小:
对随机IO来说,更大的块更好,因为这意味着更多的读取可以从一个单一的驱动器上满足。
可以配置系统以便从应用到底层存储所有的块都对齐:Innodb的块,文件系统的块,LVM分区偏移,RAID条带,磁盘扇区。

RAID缓存:
缓存读取: 没意义,因为操作系统和数据库服务器有自己的更大的缓存。
缓存预读数据: 既然innodb自己做了预读,那么raid再预读就可能没有帮助。
缓冲写入:可以更快地返回给操作系统写成功的信号,同时可以通过积累进行批量操作:把随机IO变为顺序IO。

 

9.8 使用多磁盘卷

如果只有6块盘,四个盘做raid放数据,二个做raid放日志,看起来不错,但是性能不如把六个盘都做为数据盘要慢一些。
如果有30块盘,那么分二块盘raid1出来放日志是挺不错的。

把临时目录mount到tmpfs中,可以提升filesort和使用磁盘临时表的性能。
吐槽一下HP的鼠标USB插头:
曾经见过无数的usb插头,都是USB图标朝上的,只有这个HP的鼠标,是USB图标朝下的…

9.9 网络配置

skip_name_resovle 关闭。
back_log的默认值50太小,增加到数百甚至数千,同时修改linux的somaxconn(默认128),同时修改sysctl的tcp_max_syn_back_log
增大 /proc/sys/net/ipv4/ip_local_port_range
减小 /proc/sys/net/ipv4/tcp_fin_timeout
search: TCP variables

 

9.11 选择文件系统

目录下有很多文件的话,会导致运行缓慢,但这个在ext4上不存在。需要测试。

如果系统不是很重要,比如从服务器,可以使用tunefs关闭ext3的日志记录功能。

noatime nodiratime 一定要用。

O_DIRECT会自动禁用文件系统的预读。

9.12 选择磁盘队列调度策略

默认是cfq(completely fair queueing),可以试着改成noop,或者deadline
cat /sys/block/[设备名]/queue/scheduler

 

9.13 内存交换区

这告诉内核,除非虚拟内存完全满了,否则不要使用交换分区 :
echo 0 > /proc/sys/vm/swappiness (默认为60).

O_DIRECT 并不缓存,因此操作系统并不能把mysql视为增加文件缓存的原因。
vmsstat 显示的数字是块,通常块大小为1024字节。
pt-diskstats

 

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第8章读书笔记

高性能mysql第三版第8章读书笔记

8.1 mysql配置的工作原理

查看mysqld默认会加载哪些配置文件:
/path/to/mysqld –verbose –help | grep -A 1 “Default options”

set一个变量为DEFAULT值:
把这个值赋给会话级变量可以把变量改为使用全局值; 把这个值赋给全局变量会比较糟糕,可以设置这个变量为编译内置的默认值(不一定是在配置文件中指定的值)。
sort_buffer_size 控制排序操作的内存大小,会一次性分配全部大小的内存,应该在配置文件里把它设置的不太大,如果某些查询确实需要更大的排序缓存,那么
可以在执行前增大sort_buffer_size的值,执行完之后恢复DEFAULT。
read_buffer_size与tmp_table_size也同上。

把配置文件加入 svn。

8.2 什么不该做

不要根据一些比率来调优,比如命中率。
不要使用调优脚本。

8.4 配置内存使用

innodb_file_per_table innodb_open_files
每个.idb文件都有单独的,全局的文件描述符,而myisam会用表缓存来持有打开表的文件描述符(table_open_cache)。

8.5 配置mysql的IO行为

innodb用日志把更新表的随机IO暂时变成了更新日志的顺序IO。
通过观察Innodb_os_log_written状态变量来查看innodb 对日志文件写出了多少数据。
查看10~100秒间隔的数字,然后记录峰值,比如为100KB/s,
那么1M的日志缓冲可能是足够了(innodb_log_buffer_size)。
日志文件的全部大小,应该足够容纳服务器一个小时的活动内容。

高性能事务处理需要的最佳配置是把innodb_flush_log_at_trx_commit设置为1(每次事务提交都刷新到持久化存储),并且把日志文件放到一个有电池保护的写缓存的RAID卷中,而且设置为writeback。

innodb的表空间并不只是存储表和索引,它还保存了回滚日志(旧版本行),插入缓冲(insert buffer),双写缓冲(Doublewrite buffer),以及其它内部数据结构。

当innodb从缓冲池刷新页面到磁盘时,首先把它们写到双写缓冲之中,然后再把它们写到其所属的数据区域中,可以保证每个页面的写入都是原子并且持久化的,
代价是每个页都要写两遍。
如果一个不完整的页写到了双写缓冲之中,原始的页依然会在磁盘上的它的
真实位置,当innodb恢复的时候,它将用原始页替换掉双写缓冲中的损坏页面。然后,如果双写缓冲成功写入,但写到页的真实位置失败了,innodb在恢复的时候将会使用双写缓冲中的拷贝来替换。

页的写入完整如何判断?
页的尾部有一个checksum,而且它是最后写到页的东西,所以只要检查页的内容与checksum是否一致即可。

在备库上其实可以禁止双写缓冲,或者zFS等文件系统上也可以禁用 : innodb_doublewrite = 0;

8.7 基于工作负载的配置

1) 如果所有的列加一起,长度小于8KB(半个page),那么innodb不会为text/blob大字段分配扩展存储空间,
否则会为每一个超过768字节的列分配一个或者多个完整的页做为扩展存储空间保存,而它的前缀768字节和其它列保存在一起,
至少Antelope是这样做的,Barracuda没有保存这个前缀。
768字节足以创建一个255长度的索引了,即使是utf8也够用了。
所以如果有多个text字段,就不如把它们合并到一个字段中,而且最好是自己在程序中压缩一下。

2) 如果查询中所有select的列和 order
by的列总大小超过max_length_for_sort_data字节,则采用two-pass算法,
或者任何select的列和order by
的列为BLOB/TEXT的时候,也一定会two-pass算法,可以使用substring()转化一下,
就可以用single-pass算法了。
single-pass算法较快(节省cpu),但是需要更多的内存,而且它会为每行需要排序的数据创建一个固定大小的缓冲,对于varchar列,使用的是其定义的最大长度,而不是实际长度。
所以在order by 的时候,就别select *了,只选择必须的column,或者只select id ,
然后再去用in查询。

8.9 安全和稳定的设置

read_only
禁止没有特权的用户在备库做变更,只接受从主库传输过来的变更,不接受从应用来的变更。

innodb_io_capacity
默认值是假设服务器运行在每秒100个IO操作的单硬盘上,需要调大,或许要调到上万?
innodb_read_io_threads和innodb_write_io_threads
默认是4个读4个写线程,可以把这个值设置为磁盘数量(即使后面是一个RAID控制器)。
innodb_old_blocks_time
指定一个页面从LRU链表的年轻部分转移到年老部分之前,必须经过的毫秒数。默认为0,可以尝试设置为1000(毫秒)这样的小一点的值。

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第7章读书笔记

高性能mysql第三版第7章读书笔记

7.1.4 什么情况下会出现问题

NULL值会使分区过滤无效。比如partition by range year(col)或者to_days(col)的时候,如果col值为null或者非法的时候,记录都会存放到第一个分区。
而在col上进行查询的时候,mysql都会检查两个分区。
所以可以创建一个无用的第一分区:partition p_nulls values less than(0).

7.1.5 查询优化

explain partitions select xxxx 可以查看优化器是否执行了分区过滤。
查询的时候,如果在col上使用了函数,那么将无法过滤分区。

分区的最理想情况是只有一个分区及其索引是热点,并且这个分区及索引都能在内存中。

7.4.4 在存储过程中保留注释

mysql的命令行客户端会自动过滤掉注释。
可以使用版本相关的注释,则不会被过滤。 /*!999999 this is comment */ 只有mysql版本号大于999999的时候,才会执行注释中的语句.

7.6 绑定变量

即prepared statement
当创建一个绑定变量sql时,客户端向服务端发送了一个SQL语句的原型。服务端解析并存储这个SQL语句的部分执行计划,返回给客户端一个SQL语句处理句柄。
以后在此session中,每次执行这类查询,客户端都指定使用这个句柄。

服务端只需要解析一次SQL语句,某些优化器的工作也只需要执行一次,二进制形式发送句柄和参数效率更高,而且网络开销更小。

如果在session中只执行这种SQL一次,那么反而性能不如直接mysql_query()了。

记得释放绑定变量资源。

7.7 UDF

http://www.mysqludf.org 有很多demo,扫了一眼,看到JSON相关的UDF了。

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第6章读书笔记

高性能mysql第三版第6章读书笔记

6.2.1 是否向数据库请求了不需要的数据

例如:在用户评论的时候需要查询用户头像的URL,那么某用户多次评论的时候,可能就会反复查询这个数据。缓存起来,或者在查询之前对uid去重。

6.3.2 切分查询

如果要删除大量数据,可以分批删除,这个参见 common_schema。

6.4.1 mysql客户端、服务端通讯协议

$r = mysql_query(“select * from HUGE_TABLE”, $ilnk);
while( ($row = mysql_fetch_array($r)) !== FALSE) {
//do sth
}

在mysql_query()之后,PHP已经将整个结果集缓存到内存中了。所以即使下面的while循环比较慢,也和mysql没什么关系了。
所以这样做PHP会占用大量内存? 不会的。

6.4.2 查询缓存

列表in()的比较:
在很多数据库系统中,in()等同于多个or条件,时间复杂度为O(n).
mysql中,将in()列表中的数据先排序O(nlog n)或者O(n)?,然后用二分查找的方式来确定列表中的值是否满足条件,时间复杂度为O(log n)。

6.5.8 最大值和最小值优化

select min(id) from tbl where name=’xxx’; 会全表扫描。
可以优化成select按主键排序的第一个id: select id from tbl USE INDEX(PRIMARY) where name=’xxx’ limit 1;

6.6 查询优化器的提示

DELAYED :
对insert和replace有效,mysql会将插入的行数据放入缓冲区,客户端不用等等数据的插入,mysql会在空闲时批量将数据写入。
适用场景:日志系统或者需要写入大量数据但是客户端并不需要等待。
代价是last_insert_id()失效。

6.7.1 优化count()查询

count(col) 只统计col字段非null的行。
count(*) 统计全部行。
myisam只有不带条件的count(*) 才非常快。
如果要查询带条件的count(*),而且符合条件的行的数量还占绝大多数,那么可以用全部的count(*)
减去 反条件的count(*)
在一条查询中统计多个列的不同值的数量:
select sum(IF(color=’blue’, 1, 0)) as blue, sum(IF(color=’red’, 1,0)) as
red from tbl. //在infoc的统计中很常见,感谢二三师兄。
或者
select count(color=’blue’ or NULL) as blue, count(color=’red’ or NULL) as
red from tbl.
如果不要求完全精确的count值,那么可以使用explain出来的行数。
分页的时候也可以先缓存1000条数据,每次分页都从缓存中获取,缓存的思想无处不在。

6.7.9 使用用户自定义变量

避免重复查询刚刚更新的数据:
update t1 set lastUpdated=now() where id=1;
select lastUpdated FROM t1 where id=1; 可以转化为:

update t1 set lastUpdated = now() WHERE id=1 AND @now := NOW();
select @now;
统计更新和插入的数量:
insert into t1(c1, c2) values((x,x), (y,y), (z,z)) ON DUPLICATE KEY UPDATE c1= VALUES(c1) + (
0 * ( @x := @x +1)
);
每次update时,都会对@x自增一次, 再乘以0,就不会影响到c1的值。

6.8.1 使用mysql构建一个队列表

在sql中加入注释,可以在show processlist的时候将其分辨出来….
避免使用select for update ,
可以先更新,客户端的协议会告诉你更新了几条记录。

6.8.3 UDF

可以将密集型的计算放到一些通用的服务器上,然后用c或c++的udf通过网络进行交互。

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第5章读书笔记

高性能mysql第三版第5章读书笔记

5.1.1) 索引的类型

B-Tree索引
如果查询中有某个列的范围查询(比如like x%),则其右边的所有列都无法使用索引,感觉不是很给力。

哈希索引
单点查询极快,无法范围查询,无法排序,无法部分列匹配。
应用场景:

1) 数据仓库的星型schema, 求详情。
2) 伪哈希索引: 存储url时, 如果直接在url字段做B-Tree,索引会非常大。可以再多增加一个字段,保存url的crc32,然后在crc32上面做B-Tree索引。
如果有冲突的话,只按照crc32查询,会返回多行记录。
但是用md5或者sha1又太长了,可以自己实现一个hash函数,返回整数,而不是字符串。
提到了FNV64,求详情。

3) memory 类型的表。

5.2) 索引的三大优点:

1) 减少了需要扫描的数据量。
2) 避免排序和临时表。
3) 将随机IO变为顺序IO。

5.3.5) innodb的聚簇索引

应尽量按照主键顺序插入数据,并且尽可能地使用单调增加的聚簇键的值来插入新行,避免更新主键,防止页分裂。

5.4.1) 支持多种过滤条件

  1. in() 不属于范围查询 ,只是多个等值条件查询。 即使explain()会显示type: range。
  2. 二个选择性都不高的列可以组合成一个索引,比如(sex, country)。 但是如果只按照country查询,则需要使用sex in(‘m’,’f’)来使用该索引,

5.5.1) 找到并修复损坏的表

可以通过一个不做任何操作的alter操作来重建表,例如修改表的存储引擎为当前的引擎。

5.5.3) 减少索引和数据的碎片

  1. 索引会发生碎片化
  2. 可以删除索引再重建索引来消除碎片化
  3. 如果数据没有达到稳定状态,碎片整理之后,可能会重新页分裂及碎片化,带来性能下降。

 

Posted in mysql | Tagged | Leave a comment

高性能mysql第三版第1~4章读书笔记

说明:
 读书笔记只记录我不太熟悉的内容,熟悉的就不记录了,所以对各位读者来说,没有太大意义。 感谢新公司提供这本书,虽然有点老了。

第一章读书笔记 mysql架构与历史

1.1 mysql 逻辑架构

去掉了查询缓存的简单架构:

客户端 -> [连接/线程处理->解析器->优化器] -> 存储引擎

1.3 事务

ACID

  • 原子性 Atomicity 一个事务必须被视为不可分割的最小工作单元。 事务中的操作要么全部提交,要么全部回滚。
  • 一致性 Consistency 数据库总是从一个一致性的状态,进入另外一个一致性的状态。
  • 隔离性 Isolation 一个事务所做的修改在最终提交以前,对其他事务是不可见的。
  • 持久性 Durability 一旦事务提交,其所做的修改就会永久保存到数据库中。

1.4 多版本并发控制 MVCC

原文写得很好。 这里就不摘录了。 啥时候有时间,可以提出来专门写篇文章了。

 

第三章读书笔记 服务器性能剖析

  • 资源是用来消耗并用来工作的,所以即使cpu的idle很低,也不能说明什么问题。
  • 定义性能最有效的方法是响应时间。
  • 无法测量就无法进行有效的优化。
  • 直觉可以用来指导解决问题的思路,但是不能用于确定系统的问题。决策应当尽量基于数据(相信很多PM都有同感吧)。
  • 在确认问题之前不要随便针对系统做变动。

第四章读书笔记 Schema 与数据类型优化

4.1 选择优化的数据类型

原则

  1.  更小的数据类型通常更好,因为它们占用更少的磁盘内存和CPU。
  2.  简单(可依赖:)), 比如整型比字符操作代价更低,比如要使用mysql内置的类型来储存日期时间。
  3. 避免null,除非真的要使用null,比如dt DATETIME not null default   ’0000-00-00 00:00:00′,还不如用null呢
  • 实数,不止是为了存储小数部分,比如还可以用decimal(65,0)来存储比bigint更大的整数,代价是占用更多空间与更低的性能(每4个字节存储9位数字,且小数点本身占用一个字节,待源码级别验证)。
  • 有时候又可以用bigint来取代decimal以提升性能。比如存储货币的时候,如果要精确到万分之一元,那么可以把金额乘以1万,保存为big int.
  • char会抹掉结尾空格(然后再把不足的位数用空格填充起来。),varchar则会保留结尾空格。
  • binary类型会用\0填充不足的位数。
  • binary字符串比较时,一次比较一个字节,并且是根据这个字节的值进行比较的,所以比字符串比较效率要高。
  • varchar(5) 与 varchar(255) 存储 ‘hello’的空间开销是一样的,但是应该使用更短的列,因为在使用内存临时表进行排序或者操作时,mysql会分配固定大小的内存块来保存内部值,所以varchar(255)会消耗更多的内存。(慷慨是不明智的)
  • Datetime 把日期和时间封装为YYYYMMDDHHMMSS的整数,占用8个字节,时间范围1001年到9999年,与时区无关。
  • Timestamp存储的是4字节的时间戳,与时区有关。
  • 不推荐把时间直接保存为时间戳。
  • 如果在插入时没有指定第一个timestamp字段的值,就会设置这个字段的值为当前时间。
  • innodb为每个bit列使用一个足够存储的最小整数类型((n+7)/8)来存放,所以不能节省存储空间。
  • enum允许在列中存储一组定义值中的单个值(这个定义是保存在.frm文件中的),
  • set则允许在列中存储一组定义值中的多个值,并且还有find_in_set和field这种函数。

4.4.2 计数器表

如果只有一个cnt字段,每次都要mutex锁定这条记录,然后update+1,串行肯定效率低。可以再多加一个字段slot,然后插入100或者100000条初始数据(也可以使用insert
on duplicate key update操作),
然后随机选择一个slot进行更新(行锁), 要获得总结果的话,只需要sum(cnt)即可。

 

Posted in mysql | Tagged | Leave a comment