I don't think the benefit of a covering index applies to UPDATEs (or DELETEs, for what it's worth), because if there are any matching rows, it'll have to change the row in the clustered index anyway. It might also have to change more than one secondary index, if the column you set is present in multiple indexes.
I created your table and tested EXPLAIN.
In the first query, it considers c_desc as a possible key, but it chose to use c_ref. In general, the optimizer tends to prefer unique indexes, and also tends to prefer smaller indexes.
--------------
EXPLAIN
UPDATE CustomerReferences SET customer_counter=100, description='invalidate due to X123'
WHERE customer_ref='1000001' and description <> 'immutable'
--------------
*************************** 1. row ***************************
id: 1
select_type: UPDATE
table: CustomerReferences
partitions: NULL
type: range
possible_keys: c_ref,c_desc
key: c_ref <-- optimizer prefers the unique index
key_len: 258
ref: const
rows: 1
filtered: 100.00
Extra: Using where
In the second query, it uses the PRIMARY key to do the lookup based on the id column. This is the clustered index, so it's efficient. It will match at most one row, and testing that row for the other condition won't be a big cost. Using another index won't be an improvement.
--------------
EXPLAIN
UPDATE CustomerReferences SET customer_counter=100, description='invalidate due to X123'
WHERE id=2 and description <> 'immutable'
--------------
*************************** 1. row ***************************
id: 1
select_type: UPDATE
table: CustomerReferences
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: const
rows: 1
filtered: 100.00
Extra: Using where
I think it's kind of interesting that EXPLAIN shows type: range even though the lookup is for a constant value against a unique index. I think this is a side-effect of using EXPLAIN for UPDATE.
If I try the same test with a similar SELECT, it shows type: const.
--------------
EXPLAIN
SELECT * FROM CustomerReferences
WHERE customer_ref='1000001' and description <> 'immutable'
--------------
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: CustomerReferences
partitions: NULL
type: const
possible_keys: c_ref,c_desc
key: c_ref
key_len: 258
ref: const
rows: 1
filtered: 100.00
Extra: NULL
You mentioned in a comment that you dropped the c_ref unique index. I tried that test, and this is what happened:
--------------
EXPLAIN
UPDATE CustomerReferences SET customer_counter=100, description='invalidate due to X123'
WHERE customer_ref='1000001' and description <> 'immutable'
--------------
*************************** 1. row ***************************
id: 1
select_type: UPDATE
table: CustomerReferences
partitions: NULL
type: range
possible_keys: c_desc
key: c_desc <-- it does choose the compound index
key_len: 1280
ref: const,const
rows: 2
filtered: 100.00
Extra: Using where; Using temporary
1 row in set, 1 warning (0.00 sec)
It does choose the compound index, but this doesn't make it a covering index, because it still has to update the row in the clustered index as well.
Updating based on the id works the same as before, which I would expect.
--------------
EXPLAIN
UPDATE CustomerReferences SET customer_counter=100, description='invalidate due to X123'
WHERE id=2 and description <> 'immutable'
--------------
*************************** 1. row ***************************
id: 1
select_type: UPDATE
table: CustomerReferences
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: const
rows: 1
filtered: 100.00
Extra: Using where