索引
https://www.cnblogs.com/parryyang/p/5900926.html
MySQL默认操作模式就是autocommit自动提交模式
今天掉到这个坑里了,mysql如果开了set autocommit=0,那么所有的语句一定是在一个事务里,在这种情况下,如果使用连接池,并且在查询之前没有rollback或者set autocommit=1,那么你就杯具了。因为根据mysql的默认事务级别,一致性读,你永远也取不到这个事务被开户前的数据。另外一点set autocommit= 0,会自动提交前一个事务,因此正确的作法是rollback, set autocommit =0,完成之后再set autocommit = 1;
创建表
create table unsent_emails(
`id` int(11) NOT NULL,
status enum("unsent","claimed","sent") NOT NULL,
owner int(11) not null default 0,
ts timestamp DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
INDEX `INDEX_UNIQUE`(`status`, `owner`, `ts`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
#drop table unsent_emails;
没优化前:
begin;
select id from unsent_emails
where owner =0 and status = 'unsent'
limit 10 for update;
-- result:123,456,789
update unsent_emails
set status = 'claimed', owner = connection_id()
where id in (123,456,789);
commit;
优化后:
show variables like 'autocommit';
set autocommit=1;#自动提交#ON
commit;
update unsent_emails
set status = 'claimed',owner = CONNECTION_ID()
where owner = 0 and status = 'unsent'
# set status = 'unsent',owner = 0
# where owner = CONNECTION_ID() and status = 'claimed'
limit 10;
set autocommit=0;#手动提交
#commit;
select id from unsent_emails
where owner = CONNECTION_ID() and status = 'claimed';
#将线程10,20,33,44超过十分中没有处理完的跟新为初始状态
update unsent_emails
set owner = 0,status = 'unsent'
where owner not in (10,20,33,44) and status = 'claimed'
and ts < current_timestamp - interval 10 minute;
摘自高性能mysql第三版
创建索引
ALTER TABLE users ADD INDEX index_name(name)