Thanks to all,

Best Regards,
Geetanjali Mehra
Senior Oracle and MySQL DBA Corporate Trainer and Database Security
Specialist



On Thu, Sep 4, 2014 at 2:36 PM, Akshay Suryavanshi <
akshay.suryavansh...@gmail.com> wrote:

> Hi Geeetanjali,
>
> I retried the scenario you mentioned, however I am getting consistent
> locking results on both unique and non-unique index, the preceding records
> are getting updated however just the next record is being locked "next-key
> locking". If I try to insert a new record after the "next key" it is
> getting inserted.
>
> I wonder how it is different in your situation. All I can say for now is
> InnoDB indexes are not ordered, so unsure exactly if 20 falls just right
> after the gap. Also did you delete the records from 7 through 19 or they
> are just not inserted in your test table, because that it wont be a gap,
> for the index records they are just values 6 and 20 which might sit next to
> each other in the innodb page.
>
> There are multiple blogs by experts on how the locking internals work,
>
> http://dom.as/2011/07/03/innodb-index-lock/
>
> https://www.facebook.com/note.php?note_id=479123255932
>
>
> https://blogs.oracle.com/mysqlinnodb/entry/introduction_to_transaction_locks_in
>
> http://dev.mysql.com/doc/internals/en/innodb-user-records.html
>
> "In the User Records part of a page, you'll find all the records that the
> user inserted.
>
> There are two ways to navigate through the user records, depending whether
> you want to think of their organization as an unordered or an ordered list.
>
> An unordered list is often called a "heap". If you make a pile of stones
> by saying "whichever one I happen to pick up next will go on top" -- rather
> than organizing them according to size and colour -- then you end up with a
> heap. Similarly, InnoDB does not want to insert new rows according to the
> B-tree's key order (that would involve expensive shifting of large amounts
> of data), so it inserts new rows right after the end of the existing rows
> (at the top of the Free Space part) or wherever there's space left by a
> deleted row.
> But by definition the records of a B-tree must be accessible in order by
> key value, so there is a record pointer in each record (the "next" field in
> the Extra Bytes) which points to the next record in key order. In other
> words, the records are a one-way linked list. So InnoDB can access rows
> in key order when searching."
>
> Hope this helps.
>
> Cheers!!!
> Akshay
>
>
> On Thu, Sep 4, 2014 at 9:48 AM, geetanjali mehra <
> mailtogeetanj...@gmail.com> wrote:
>
>> Dear Akshay,
>>
>>
>> Thanks for you reply, You are really great. Now , one more confusion.
>>
>>
>> mysql> create table test.new as select id,name from City;
>>
>> Query OK, 4079 rows affected (0.18 sec)
>>
>> Records: 4079  Duplicates: 0  Warnings: 0
>>
>>
>>
>> mysql> select * from new limit 15;
>>
>> +----+-------------------+
>>
>> | id | name              |
>>
>> +----+-------------------+
>>
>> |  1 | Kabul             |
>>
>> |  2 | Qandahar          |
>>
>> |  3 | Herat             |
>>
>> |  4 | Mazar-e-Sharif    |
>>
>> |  5 | Amsterdam         |
>>
>> |  6 | Rotterdam         |
>>
>> |11|hhh                               |
>>
>> | 20 | ´s-Hertogenbosch  |
>>
>> | 21 | Amersfoort        |
>>
>> | 22 | Maastricht        |
>>
>> | 23 | Dordrecht         |
>>
>> | 24 | Leiden            |
>>
>> | 25 | Haarlemmermeer    |
>>
>> | 26 | Zoetermeer        |
>>
>> | 27 | Emmen             |
>>
>> | 28 | Zwolle            |
>>
>> Now,
>>
>> *Session 1*
>>
>> *Session 2*
>>
>>
>>
>> mysql> begin;
>>
>> Query OK, 0 rows affected (0.01 sec)
>>
>>
>>
>> mysql> select * from new where id between 9 and 15 for update;
>>
>> +----+------+
>>
>> | id | name |
>>
>> +----+------+
>>
>> | 11 | hhh  |
>>
>> +----+------+
>>
>> 1 row in set (0.00 sec)
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> mysql> begin;
>>
>> Query OK, 0 rows affected (0.00 sec)
>>
>>
>>
>> mysql> insert into new values(17,'fff');
>>
>> (session is hanging)
>>
>> mysql> insert into new values(18,'fff');
>>
>> (session is hanging)
>>
>> mysql> insert into new values(19,'fff');
>>
>> (session is hanging).
>>
>>
>>
>>
>>
>> mysql> insert into new values(20,'fff');
>>
>> Query OK, 1 row affected (0.00 sec)
>>
>>
>>
>> mysql> insert into new values(21,'fff');
>>
>> Query OK, 1 row affected (0.01 sec)
>>
>>
>>
>> mysql> insert into new values(8,'fff');
>>
>> (session hang)
>>
>> mysql>
>>
>> mysql> insert into new values(7,'fff');
>>
>> (session hang)
>>
>> mysql> insert into new values(6,'fff');
>>
>> (session hang)
>>
>> mysql> insert into new values(5,'ggg');
>>
>> Query OK, 1 row affected (0.00 sec)
>>
>>
>>
>>
>>
>> I tried the above scenario with index and without index.  Without index
>> it is showing the same behaviour as before. Using non-unique index, it is
>> not locking the next value (20)immediately after the gap. But it is locking
>> a row with id=6, the value immediately before the gap.  Can you explain
>> me the same?
>>
>> When I tried the same scenario with unique index, this is what I got from
>> another session:
>>
>>
>> mysql> insert into new values(20,'jjj');
>>
>> (hang)
>>
>> mysql> insert into new values(6,'jjj');
>>
>> ERROR 1062 (23000): Duplicate entry '6' for key 'idx1'
>>
>>
>> Here it is locking 20 , but not 6.
>>
>> Best Regards,
>> Geetanjali Mehra
>> Senior Oracle and MySQL DBA Corporate Trainer and Database Security
>> Specialist
>>
>>
>>
>> On Wed, Sep 3, 2014 at 10:59 PM, Akshay Suryavanshi <
>> akshay.suryavansh...@gmail.com> wrote:
>>
>>> Can you try the same on a big table, I think optimizer is choosing a FTS
>>> over an index lookup.
>>>
>>>
>>> On Wed, Sep 3, 2014 at 8:25 PM, geetanjali mehra <
>>> mailtogeetanj...@gmail.com> wrote:
>>>
>>>> This is what I am doing.
>>>>
>>>> mysql> select * from new;
>>>> +------+------+
>>>> | c1   | c2   |
>>>> +------+------+
>>>> |    5 |    5 |
>>>> |   10 |   10 |
>>>> |   15 |   15 |
>>>> |   20 |   20 |
>>>> |   30 |   30 |
>>>> +------+------+
>>>>
>>>>
>>>> Now,
>>>>
>>>> Session 1
>>>>
>>>>
>>>> mysql> begin;
>>>>
>>>> Query OK, 0 rows affected (0.00 sec)
>>>>
>>>>
>>>>
>>>> mysql> select * from new where c1 between 10 and 25 for update;
>>>>
>>>> +------+------+
>>>>
>>>> | c1   | c2   |
>>>>
>>>> +------+------+
>>>>
>>>> |   10 |   10 |
>>>>
>>>> |   15 |   15 |
>>>>
>>>> |   20 |   20 |
>>>>
>>>> +------+------+
>>>>
>>>> 3 rows in set (0.00 sec)
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> mysql>begin;
>>>>
>>>> mysql> insert into new values(29,29);
>>>>
>>>> (session is hanging)
>>>>
>>>> mysql> insert into new values(31,31);
>>>>
>>>> (session is hanging
>>>>
>>>>
>>>> The last value on my table is 30.  Still it is not allowing me to
>>>> insert 31.
>>>>
>>>> I tried the scenario without index on column c1 and then with
>>>> non-unique index on column c1 and then unique index.  I am getting the same
>>>> result. It seems that it is putting up lock on complete table.
>>>>
>>>> The scenario is working fine only when I made c1 primary key.  After
>>>> making c1 primary key, I am able to insert value higher than 30.
>>>>
>>>> Can you please try the same scenario at your end?
>>>>
>>>>
>>>>
>>>>
>>>> Best Regards,
>>>> Geetanjali Mehra
>>>> Senior Oracle and MySQL DBA Corporate Trainer and Database Security
>>>> Specialist
>>>>
>>>>
>>>>
>>>> On Tue, Sep 2, 2014 at 1:53 PM, Akshay Suryavanshi <
>>>> akshay.suryavansh...@gmail.com> wrote:
>>>>
>>>>> Hello Geetanjali,
>>>>>
>>>>> Apologies if I have confused you with the "normal Select" notation. I
>>>>> meant to write with repeatable-read mode in mind, but looks like that is
>>>>> not an issue, since you already tested this scenario with that isolation
>>>>> mode.
>>>>>
>>>>> Moving further to the original issue.
>>>>>
>>>>> Do you have an index on column c1. Is the query "Select * from new
>>>>> where c1 between 12 and 17 for update;" using index ? If there is no
>>>>> index on the particular column, then InnoDB locks out whole table from
>>>>> other transactions. Which is the case you mentioned. Also this can be
>>>>> dangerous. Once you have indexed the column checkout the innodb status, 
>>>>> you
>>>>> will see the necessary locking. Also try updating values beyond the
>>>>> boundary values.
>>>>>
>>>>> So most important fact to know here is the involvement of secondary
>>>>> indexes to introduce record locking, gap locking, and how their absence
>>>>> will affect the transaction. As to "Why" this is happening ? It should be
>>>>> understood that in InnoDB secondary keys are appended to PRIMARY index, so
>>>>> if there is no index to search the records PRIMARY index values cannot be
>>>>> filtered. In absence of secondary indexes a full scan is needed. And
>>>>> finally Innodb table is one big Index (Clustered table).
>>>>>
>>>>> *By default, InnoDB operates in REPEATABLE READ
>>>>> <http://dev.mysql.com/doc/refman/5.6/en/set-transaction.html#isolevel_repeatable-read>
>>>>>  transaction
>>>>> isolation level and with theinnodb_locks_unsafe_for_binlog
>>>>> <http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_locks_unsafe_for_binlog>
>>>>>  system
>>>>> variable disabled. In this case, InnoDB uses next-key locks for searches
>>>>> and index scans, which prevents phantom rows.*
>>>>>
>>>>> So Index scan above is infact a Full-table-scan (full index scan)
>>>>>
>>>>> Please try it out and let me know if you observe any difference.
>>>>>
>>>>> Cheers!!!
>>>>>  Akshay
>>>>>
>>>>>
>>>>> On Tue, Sep 2, 2014 at 11:59 AM, geetanjali mehra <
>>>>> mailtogeetanj...@gmail.com> wrote:
>>>>>
>>>>>> Dear Akshay,
>>>>>>
>>>>>> ASFIK, normal selects are always non-locking read and they do not put
>>>>>> any
>>>>>> locks.
>>>>>> Select..., Select..........where......,Select
>>>>>> ........where......between
>>>>>>
>>>>>> Does above select statement will use next-key locking and/or gap
>>>>>> locking?
>>>>>> I dont think so.
>>>>>>
>>>>>> Please correct me if I am wrong.
>>>>>>
>>>>>>
>>>>>> Best Regards,
>>>>>> Geetanjali Mehra
>>>>>> Senior Oracle and MySQL DBA Corporate Trainer and Database Security
>>>>>> Specialist
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, Aug 29, 2014 at 11:46 AM, Akshay Suryavanshi <
>>>>>> akshay.suryavansh...@gmail.com> wrote:
>>>>>>
>>>>>> > Geetanjali,
>>>>>> >
>>>>>> > There is a difference between next-key locking, gap locking and
>>>>>> locking
>>>>>> > reads.
>>>>>> >
>>>>>> > Next-key locking and gap-locking are used with normal Selects
>>>>>> statement in
>>>>>> > Innodb, whereas locking reads wont release a lock on the whole
>>>>>> column until
>>>>>> > transaction completed, and not just selected values.
>>>>>> >
>>>>>> > May be you can try your example with SELECT... LOCK IN SHARE MODE;
>>>>>> >
>>>>>> > Cheers!!!
>>>>>> > Akshay Suryawanshi
>>>>>> >
>>>>>> >
>>>>>> > On Fri, Aug 29, 2014 at 11:22 AM, geetanjali mehra <
>>>>>> > mailtogeetanj...@gmail.com> wrote:
>>>>>> >
>>>>>> >> Thanks for your reply.
>>>>>> >>
>>>>>> >> I read those docs. Still my doubt is at the same stage.  Please
>>>>>> clarify
>>>>>> >> the
>>>>>> >> same to me.
>>>>>> >>  Should not other sessions be allowed to insert the rows beyond
>>>>>> that
>>>>>> >> range.?
>>>>>> >>
>>>>>> >> As far as I understand, Innodb brought the concept of next-key
>>>>>> locks so as
>>>>>> >> to prevent phantom problem.   So, it is clear to me that issuing
>>>>>> the below
>>>>>> >> query
>>>>>> >>
>>>>>> >> Select * from new where c1 between 12 and 17 for update;
>>>>>> >>
>>>>>> >> will not allow other sessions to insert any value between 12 and
>>>>>> 17.
>>>>>> >>
>>>>>> >> But if i am trying to insert 20 from other session, it is not
>>>>>> allowed. Why
>>>>>> >> this is so? The session is hanging.
>>>>>> >>
>>>>>> >> Best Regards,
>>>>>> >> Geetanjali Mehra
>>>>>> >> Senior Oracle and MySQL DBA Corporate Trainer and Database Security
>>>>>> >> Specialist
>>>>>> >>
>>>>>> >>
>>>>>> >>
>>>>>> >> On Thu, Aug 28, 2014 at 2:26 AM, shawn l.green <
>>>>>> shawn.l.gr...@oracle.com>
>>>>>> >> wrote:
>>>>>> >>
>>>>>> >> >
>>>>>> >> >
>>>>>> >> > On 8/26/2014 1:12 AM, geetanjali mehra wrote:
>>>>>> >> >
>>>>>> >> >> Hello to all,
>>>>>> >> >> In repeatable read isolation level, when we issue:
>>>>>> >> >>
>>>>>> >> >> Select * from new where c1 between 12 and 17 for update;
>>>>>> >> >>
>>>>>> >> >> this range will be locked by innodb by using next-key locks.
>>>>>> >> >>
>>>>>> >> >> But, why is is preventing any other session to insert any value
>>>>>> beyond
>>>>>> >> >> that
>>>>>> >> >> range; any value above the range and any value below the range.
>>>>>> I am
>>>>>> >> >> unable
>>>>>> >> >> to understand this.
>>>>>> >> >>
>>>>>> >> >
>>>>>> >> > I believe you are confusing gap locking (the space between the
>>>>>> values)
>>>>>> >> and
>>>>>> >> > next-key locking (the space after the range).
>>>>>> >> >
>>>>>> >> >
>>>>>> http://dev.mysql.com/doc/refman/5.6/en/innodb-record-level-locks.html
>>>>>> >> >
>>>>>> >> > See also:
>>>>>> >> >
>>>>>> http://dev.mysql.com/doc/refman/5.6/en/innodb-next-key-locking.html
>>>>>> >> > http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html
>>>>>> >> >
>>>>>> >> >
>>>>>> >> >
>>>>>> >> >> Best Regards,
>>>>>> >> >> Geetanjali Mehra
>>>>>> >> >> Senior Oracle and MySQL DBA Corporate Trainer and Database
>>>>>> Security
>>>>>> >> >> Specialist
>>>>>> >> >>
>>>>>> >> >>
>>>>>> >> > Yours,
>>>>>> >> > --
>>>>>> >> > Shawn Green
>>>>>> >> > MySQL Senior Principal Technical Support Engineer
>>>>>> >> > Oracle USA, Inc. - Hardware and Software, Engineered to Work
>>>>>> Together.
>>>>>> >> > Office: Blountville, TN
>>>>>> >> >
>>>>>> >> > --
>>>>>> >> > MySQL General Mailing List
>>>>>> >> > For list archives: http://lists.mysql.com/mysql
>>>>>> >> > To unsubscribe:    http://lists.mysql.com/mysql
>>>>>> >> >
>>>>>> >> >
>>>>>> >>
>>>>>> >
>>>>>> >
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>

Reply via email to