索引

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第三版

update 替代 select for update 后update

创建索引

ALTER TABLE users ADD INDEX index_name(name)
 

相关文章: